When I have fetched objects from firebase realtime database into ArrayList then they are not sorted properly using Collections.sort() method. I have total 17 objects(posts) in my fetched ArrayList in which 2 objects are 1 month ago and rest 15 are under a month. Collection sorts properly these 15 objects but these 2 objects are added before 15 objects in sorting.
I am sorting these objects into ascending order of timestamp to show newer posts first and older at last. But very old posts (more than 1 month) are added before on sorting.
I have following PostModel class structure for Firebase
PostModel Class:
public class PostModel {
public String title,description;
public long timestamp;
public PostModel(){}
public PostModel(String title, String description,long timestamp) {
this.title = title;
this.description = description;
this.timestamp = timestamp;
}
}
I have passed timestamp into above class objects for insertion as System.currentTimeMillis(); and sorted using following way.
Collections.sort(postsObjs, new Comparator<PostModel>() {
#Override
public int compare(PostModel o1, PostModel o2) {
return (int) (o2.timestamp - o1.timestamp);
}
});
Help me to sort my objects properly. Thanks
Edit: I have 17 objects in my ArrayList instead of 7 and rest is same
A compare method should return -1,0 or 1;
0: if (x==y)
-1: if (x < y)
1: if (x > y)
try this:
return Long.compare(o2.timestamp - o1.timestamp);
I am trying to work with a seemingly complex HashMap object to pupulate my expandable Listview in android.
The generic parameters for my HashMap as as shown below:
//HashMap<Map<YEAR,MONTH>,List<DAYS>>
HashMap<Map<Integer,Integer>,List<Integer>
I am using the Hash map to monitor day, month and year when an event took place. So assuming an event took place on 12th, 20th and 25th in May 2013, I would do something as this:
HashMap<Integer,Integer>,List<Integer>> events = new HashMap<Integer,Integer>,List<Integer>();
HashMap<Integer,Integer> yearMonth = new HashMap<Integer,Integer>();
yearMonth.put(2013,5);
events.put(yearMonth,Arrays.asList(new Integer[]{12,20,25}));
I have created an adapter for my expandable list view and it displays fine as shown below. Now I want to be able to sort the above HashMap, first by Year and Month so that my listview will display events in 2014 at the top following by 2013, 2012 .... in that order.
Is this possible?
Thanks.
Well, I just read "sort a hasmap". In the case you really want sort your data, a hashmap is definitely the wrong one.
Maybe you should think about using a linkedlist...
Create your own class instead of the hashmap, and adjust the adapter to suit those objects.
Then you can implement your own sorting, by implementing Comparable and creating a compareTo() method in your class.
This gives you all the control you need. For example:
public class myEvent implements Serializable, Comparable<myEvent>
{
private Integer day;
private Integer month;
private Integer year;
public myEvent( Integer day, Integer month, Integer year, <your other data> )
{
// Save the stuff here
this.day = day;
this.month = month;
this.year = year;
}
// Create getDay(), getMonth(), getYear() methods for each parameter
public int compareTo( myEvent another )
{
// Here, compare the two events year by year, month by month, and day by day
if ( this.year.compareTo( another.getYear() ) == 0 )
{
if ( this.month.compareTo( another.getMonth() ) == 0 )
{
return this.day.compareTo( another.getDay() );
} else {
return this.month.compareTo( another.getMonth() );
}
} else {
return this.year.compareTo( another.getYear() );
}
}
}
EDIT: When you want to sort a list of those myEvent objects, you can use the Collection api to make use of the Comparable implementation:
List<myEvent> allevents = new ArrayList<myEvent>();
// Add to the list
...
// Now sort it.
Collections.sort( allevents );
Good luck.
I'm trying to write a getter which takes specific data from an enum and returns a double, which I will use later in my code and I'm not sure how to go about it. This is what I've come up with so far:
//This getter takes the enum of Month and converts it so it returns the mean precipitation of a certain month
public double getPrecipitationMonth(Month month){
//more in here
return this.precipitationMonths[month.ordinal()];
The enum in question is the months of the year ie {JANUARY, FEBRUARY...} and the data for each month is in a separate file.
I'm new to programming - hope you can help! Thank you
I think your general idea is very sound. But I'd just use a Map like so:
Map<Month,Double> data = new HashMap<>;
for(Row row : readFromFile()){
data.put(row.getMonth(), row.getData());
}
So that it's more obvious.
You can use a HashMap for this, assigning enum values as keys
enum Month {
// Your enum
}
HashMap< Month, Double > monthPrecipitation = new HashMap< Month, Integer >();
public double getPrecipitationMonth( Month month ) {
return monthPrecipitation.get( month );
}
I would write eum something like that:
public enum Month {
JAN (1.0),
FEB (2.0),
MAR (3.0);
private double mId;
public static Month fromDoubleToEnum( double value ) throws Exception{
for ( Month c : Month.values() ) {
if ( c.mId == value ) {
return c;
}
}
throw new Exception( "Illegal Month value: " + value );
}
public double fromEnumToDouble(){
return mId;
}
private EModule (double num){
mId = num;
}
}
Here we have method: fromEnumToDouble that returns double on enum.
Test
public static void main(String[] args) {
Month mod = Month.FEB;
double toDouble = mod.fromEnumToDouble();
System.out.println(toDouble); // out 2.0
}
Use an EnumMap to store your precipitationMonths array instead.
EnumMap<Month,Something> precipitationMonths = new EnumMap<Month,Something>(Month.class);
precipitationMonths.put(Month.JANUARY, someValue); // Add a value
Something someValue = precipitationMonths.get(Month.JANUARY); // Get a value
Regarding that your data are located in file you need to create a class that will store that data and be able to map them.
The Java has really poor support for calendar, but you can work with it using Calendar class
You can create a enum for calendar but it is not mandatory.
enum Month{
JANUARY(Calender.JANUARY);
private final int month;
Month(int month) {
this.month = month;
}
public int month() {
return month;
}
}
When you solve the first problem of matching the data from file with months.
private final Map<Month,Double> precipitationMap = new EnumMap<>();
private void assignPrecipitation(Month month, double precipitation) {
this.precipitationMap.put(month,precipitation);
}
public double getPrecipitation(Month month) {
if(this.precipitationMap.contains(month) {
return this.precipitationMap.get(month).doubleValue();
}
throw new IllegalStateException("The Precipitation was not found for: " + myCalendar);
}
I am implementing my own Java class for sorting a List<T> in eclipse. I made break points in comparsion statements and it does not work as I unexpected!
Here is the code :
if(doy2 < don && doy1>don)
{
return 1;
}
else if (doy2 > don && doy1<don)
{
return -1;
}
else
{
return 0;
}
Even though the doy2 > don && doy1<don statement evaluates to true, and the code reaches return -1, but it also goes to else part and return 0. Why exactly?
Edited: The Complete code
public class DateCompartor implements Comparator<BirthdayContact> {
#Override
public int compare(BirthdayContact arg0, BirthdayContact arg1) {
Date now=new Date();
Date bd1=arg0.GetBirthDay();
Date bd2=arg1.GetBirthDay();
DateTime dt1=new DateTime(bd1);
DateTime dtnow=new DateTime(now);
DateTime dt2=new DateTime(bd2);
int doy1=dt1.getDayOfYear();
int doy2=dt2.getDayOfYear();
int don=dtnow.getDayOfYear();
if(doy2 < don && doy1>don)
{
return 1;
}
else if (doy2 > don && doy1<don)
{
return -1;
}
else
{
return 0;
}
}
}
I am comparing two dates with current date, and which ever is closer to current date, should get upper in the list.
I'd rebuild your code and step through it again. The 'weirdness' that you note might be due to the source and bytecode being out of synch.
I'd ask that you post the entire Comparable implementation. Comparator usually compares two objects, but your comparison statements appear to involve three. Perhaps you can clarify exactly what you're doing.
Be assured that your code is incorrect. You have a mental model of how this should work in mind, but your assumptions don't match reality. Your job is to bring them back into harmony.
UPDATE:
Given the new information, I'd certainly not code it the way you did. I'd calculate the difference from each date to today's time and compare those. I'm not interested enough to test it out myself. See if that works out better for you.
public class DateCompartor implements Comparator<BirthdayContact> {
#Override
public int compare(BirthdayContact arg0, BirthdayContact arg1) {
Date now=new Date();
// Read Sun's Java coding standards; these don't follow the standard.
Date bd1=arg0.GetBirthDay();
Date bd2=arg1.GetBirthDay();
long dist1 = Math.abs(bd1.getTime() - now.getTime());
long dist2 = Math.abs(bd2.getTime() - now.getTime());
return dist1.compareTo(dist2); // Might need wrapper Long here.
}
}
I seem to have faced this problem many times and I wanted to ask the community whether I am just barking up the wrong tree. Basically my question can be distilled down to this: if I have an enum (in Java) for which the values are important, should I be using an enum at all or is there a better way, and if I do use an enum then what is the best way to reverse the lookup?
Here's an example. Suppose I want to create a bean representing a specific month and year. I might create something like the following:
public interface MonthAndYear {
Month getMonth();
void setMonth(Month month);
int getYear();
void setYear(int year);
}
Here I'm storing my month as a separate class called Month, so that it is type-safe. If I just put int, then anyone could pass in 13 or 5,643 or -100 as a number, and there would be no way to check for that at compile-time. I'm restricting them to put a month which I'll implement as an enum:
public enum Month {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER;
}
Now suppose that I have some backend database I want to write to, which only accepts the integer form. Well the standard way to do this seems to be:
public enum Month {
JANUARY(1),
FEBRUARY(2),
MARCH(3),
APRIL(4),
MAY(5),
JUNE(6),
JULY(7),
AUGUST(8),
SEPTEMBER(9),
OCTOBER(10),
NOVEMBER(11),
DECEMBER(12);
private int monthNum;
public Month(int monthNum) {
this.monthNum = monthNum;
}
public getMonthNum() {
return monthNum;
}
}
Fairly straightforward, but what happens if I want to read these values from the database as well as writing them? I could just implement a static function using a case statement within the enum that takes an int and returns the respective Month object. But this means if I changed anything, then I would have to change this function as well as the constructor arguments - change in two places. So here's what I've been doing. First off I created a reversible map class as follows:
public class ReversibleHashMap<K,V> extends java.util.HashMap<K,V> {
private java.util.HashMap<V,K> reverseMap;
public ReversibleHashMap() {
super();
reverseMap = new java.util.HashMap<V,K>();
}
#Override
public V put(K k, V v) {
reverseMap.put(v, k);
return super.put(k,v);
}
public K reverseGet(V v) {
return reverseMap.get(v);
}
}
Then I implemented this within my enum instead of the constructor method:
public enum Month {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER;
private static ReversibleHashMap<java.lang.Integer,Month> monthNumMap;
static {
monthNumMap = new ReversibleHashMap<java.lang.Integer,Month>();
monthNumMap.put(new java.lang.Integer(1),JANUARY);
monthNumMap.put(new java.lang.Integer(2),FEBRUARY);
monthNumMap.put(new java.lang.Integer(3),MARCH);
monthNumMap.put(new java.lang.Integer(4),APRIL);
monthNumMap.put(new java.lang.Integer(5),MAY);
monthNumMap.put(new java.lang.Integer(6),JUNE);
monthNumMap.put(new java.lang.Integer(7),JULY);
monthNumMap.put(new java.lang.Integer(8),AUGUST);
monthNumMap.put(new java.lang.Integer(9),SEPTEMBER);
monthNumMap.put(new java.lang.Integer(10),OCTOBER);
monthNumMap.put(new java.lang.Integer(11),NOVEMBER);
monthNumMap.put(new java.lang.Integer(12),DECEMBER);
}
public int getMonthNum() {
return monthNumMap.reverseGet(this);
}
public static Month fromInt(int monthNum) {
return monthNumMap.get(new java.lang.Integer(monthNum));
}
}
Now this does everything I want it to, but it still looks wrong. People have suggested to me "if the enumeration has a meaningful internal value, you should be using constants instead". However, I don't know how that approach would give me the type-safety I am looking for. The way I've developed does seem overly complicated though. Is there some standard way to do this kind of thing?
PS: I know that the likelihood of the government adding a new month is...fairly unlikely, but think of the bigger picture - there are plenty of uses for enums.
This is a very common pattern, and it's fine for enums... but it can be implemented more simply. There's no need for a "reversible map" - the version which takes the month number in the constructor is better for going from Month to int. But going the other way isn't too hard either:
public enum Month {
JANUARY(1),
FEBRUARY(2),
MARCH(3),
APRIL(4),
MAY(5),
JUNE(6),
JULY(7),
AUGUST(8),
SEPTEMBER(9),
OCTOBER(10),
NOVEMBER(11),
DECEMBER(12);
private static final Map<Integer, Month> numberToMonthMap;
private final int monthNum;
static {
numberToMonthMap = new HashMap<Integer, Month>();
for (Month month : EnumSet.allOf(Month.class)) {
numberToMonthMap.put(month.getMonthNum(), month);
}
}
private Month(int monthNum) {
this.monthNum = monthNum;
}
public int getMonthNum() {
return monthNum;
}
public static Month fromMonthNum(int value) {
Month ret = numberToMonthMap.get(value);
if (ret == null) {
throw new IllegalArgumentException(); // Or just return null
}
return ret;
}
}
In the specific case of numbers which you know will go from 1 to N, you could simply use an array - either taking Month.values()[value - 1] or caching the return value of Month.values() to prevent creating a new array on every call. (And as cletus says, getMonthNum could just return ordinal() + 1.)
However, it's worth being aware of the above pattern in the more general case where the values may be out of order, or sparsely distributed.
It's important to note that the static initializer is executed after all the enum values are created. It would be nice to just write
numberToMonthMap.put(monthNum, this);
in the constructor and add a static variable initializer for numberToMonthMap, but that doesn't work - you'd get a NullReferenceException immediately, because you'd be trying to put the value into a map which didn't exist yet :(
There's a way easier way of doing this. Every enum has an ordinal() method return it's number (starting from zero).
public enum Month {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER;
public Month previous() {
int prev = ordinal() - 1;
if (prev < 0) {
prev += values().length;
}
return values()[prev];
}
public Month next() {
int next = ordinal() + 1;
if (next >= values().length) {
next = 0;
}
return values()[next];
}
}
As for how to store this in a database, it depends on what persistence framework (if any) you're using. JPA/Hibernate have the option of mapping enum values by either number (ordinal) or name. Months are something you can probably take as non-changing so just use the ordinal. To get a specific value:
Month.values()[ordinalNumber];
I'm probably far behind the pack in an answer here but I tend to implement it a little bit simpler. Don't forget that 'Enum' has a values() method.
public static Month parse(int num)
{
for(Month value : values())
{
if (value.monthNum == num)
{
return value;
}
}
return null; //or throw exception if you're of that mindset
}
You shouldn't use ordinal() for this kind of thing, for the sample with months it would work (because it will not be extended) but one of the good things with enums in java is that they are designed to be possible to extend without breaking things. If you start relying on ordinal() things will break if you add some value in the middle.
I would do it like Jon Skeet suggests (he wrote it while I was writing this) but for cases where the internal number representation is in a well defined range of say 0 to 20 (or something) I would probably not use a HashMap and introduce autoboxing of the int but rather use an ordinary array (like Month[12]) but both are fine (Jon later changed his post to include this suggestion).
Edit: For the few enums where there is a natural order (like sorted months) ordinal() is probably safe to use. The problems you risk running into if you persist it will appear for things where someone might change the order of the enum. Like if:
the "enum { MALE, FEMALE }" becomes an "enum {UNKNOWN, FEMALE, MALE}" when someone extends the program in the future not knowing that you rely on ordinal.
Giving Jon a +1 for writing the same I was just writing.