?
Solved

How to sort a set of objects based on a certain field?

Posted on 2011-05-12
30
Medium Priority
?
290 Views
Last Modified: 2012-06-22
How to sort below set of objects, so that the returned filesDb set will have records sorted by fileDate field in this object?

In SampleFile object, it has these fields:
fileDate and fileId
file date is like:
2011-05-11
2011-05-10

private Set<SampleFile> getFiles(Set<SampleFile> files) {
    Set<SampleFile> filesDb = new HashSet();

    for (SampleFile f : files) {
      filesDb.add(fileDao.get(f.getFileId()));
    }
    return filesDb;
  }

Thanks.
0
Comment
Question by:heyday2004
  • 12
  • 9
  • 7
  • +1
30 Comments
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35748170
In the definition of the SampleFile class
you define the method
int compareTo(SampleFile f){

}

so that it should return poistibve when the date is later and negative oppsotely

After you've done it pt your objcets in a list
 Collections.sort(list)
method will produce ciorrectly ordered list

0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35748171
Use a Comparator (assuming String)
Collections.sort(samples, new Comparator<SampleFile>() {
    public int compare(SampleFile s1, SampleFile s2) {
        return s1.getFileDate().compareTo(s2.getFileDate());
    }
});

Open in new window

0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35748191
You don't have to assume that date is  a string

you just return

if(s1.getFileDate().befor(s2.getFileDate())return -1;
else return 1;

It is not good idea to assume the dtaes are strings
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35748295
>>You don't have to assume that date is  a string

You have to use whatever data type it is - obviously ;)
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35748332
I'd rather say you have to use wahtever business requirements are -
if they ask you to order your onbjects by date - no matter
how thsi adte uis stored in your internal structire they would not
appreciate when your ordering will be wriong judging by date,
so if I'm programming this part I have to take care of this and
first parse strings into the dates and compare dates, if this is the requirement
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35748357
heyday2004 - to avoid any more pointless speculation - is the field Date or String?
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35748381
Actually - you can ignore that question sorry - my code example will work in either case
0
 
LVL 92

Assisted Solution

by:objects
objects earned 176 total points
ID: 35751363
heres an example of how to do the sorting

http://helpdesk.objects.com.au/java/how-to-sort-java-list-using-custom-ordering

you'll also need to copy the sorted list into something like a LinkedHashSet to retain the order
http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
0
 

Author Comment

by:heyday2004
ID: 35751813
The field Date. Thanks!
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35751826
Yes, of course you have to compare it as dates, but CEHJ was right - he was lucky - I bet
he was thinknig of them as strings when he was writing this code, but
java.util.Date() overrides method compareTo() , so indeed his code works as you would probably need
0
 

Author Comment

by:heyday2004
ID: 35752449
Thanks for all the replies. what I need is to sort Set, not List.

Listed below is what I got from the replies, will it return a sorted Set (filesDb) by FileDate (that's all my purpose)? Any further suggestion to get a sorted set of filesDb (by FileDate)?

private Set<SampleFile> getFiles(Set<SampleFile> files) {
    Set<SampleFile> filesDb = new HashSet();

    for (SampleFile f : files) {
      filesDb.add(fileDao.get(f.getFileId()));
    }

    Collections.sort(filesDb, new Comparator<SampleFile>() {
    public int compare(SampleFile s1, SampleFile s2) {
        return s1.getFileDate().compareTo(s2.getFileDate());
    }
});

    return filesDb;

  }

Thanks a lot.
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35752468
Sorry, yes. You can either:

a. add the contents of the Set to a List and sort that
b. use the Comparator to maintain a SortedSet
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35752483
e.g.
private SortedSet<SampleFile> getSortedFiles(Set<SampleFile> files) {
	SortedSet<SampleFile> filesDb = new TreeSet(new Comparator<SampleFile>() {
	    public int compare(SampleFile s1, SampleFile s2) {
		return s1.getFileDate().compareTo(s2.getFileDate());
	    }
	});
	filesDb.addAll(files);
	return filesDb;
    }

Open in new window

0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35752496
A small adjustment - should have been
SortedSet<SampleFile> filesDb = new TreeSet<SampleFile>(new Comparator<SampleFile>() {

Open in new window

0
 
LVL 92

Assisted Solution

by:objects
objects earned 176 total points
ID: 35753030
> Thanks for all the replies. what I need is to sort Set, not List.

yes mentioned that earlier, you'll need to use a Set that supports ordering. nit a HashSet
0
 

Author Comment

by:heyday2004
ID: 35813267
Sorry for my late replies because I was out of town. One last question:
For CEHJ's solution:
If my original set has:
record A
record b

and if both records have exactly the same FileDate

Then seems in the final sortedSet, only record A will be added in the sortedSet (since it provides the same compare result).

Please advise if this is true when we used SortedSet (based on the running result, it seems to be true). Thanks!
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813295
No, in CEHJ solution they will both be in the resulting TreeSet- you only cannot predict in which order
these two records will appear - which is waht should be expected because they have the
same date.
It is true that Set does not allow duplicates, but this is the Set of your objects as a whole,
so your objects will not be identical therefore they can both be memebers of the TreeSet,
it is only comparrator will retun zero, so their order relative to each other will not be defined,
 but none of these objects will be exuded from  the resulting ordered set.
So you should not worry about losing them.
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813340

In general, if your collection of objects can contain identical objects
then you probably want to use List instead of Set.
The ordering part will work the same way, but List
can contain duplicate elements, whereas Set cannot.
But in your setting of the problem you used Set, so it is natural to assume
taht you don't have identiacl objects.
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813410
You know, it looks I was avtually wriong - I'm doing some experiemnts
and it returns to me just one file when I start with two files
with the same date.
I'll continue, and let you know when I figure out.
It ios probably better not to use TreeSet
0
 

Author Comment

by:heyday2004
ID: 35813431
Thanks for the replies. I'm still confused since in CEHJ's solution, the input Set: files have object A and B. And my output of filesDb (sorted Set) seems only contain one object (A or B). The filesDb is a new sorted Set, with record added like this:

for (SampleFile f : files) {
  filesDb.addAll(file....);
}      
return filesDb;

Any possibility that in this case, the returned filesDb might just contain record A or B but not both?

Thanks!
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813441
Yes, that's what I saw also.
I made a set of two files (objects having date and name)
and they had the same date and different name.
After sorting with that method of my original set
I got a SortedSet with only one object.
So I think we need to change it from TreeSet

0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813480

Ok. This is how it works with two files having thwe same date:

import java.util.*;

public class SortedFiles {

    public static void main(String [] args){

        HashSet set = new HashSet();

        SampleFile f1 = new SampleFile("a", new java.util.Date());

         SampleFile f2 = new SampleFile("b", new java.util.Date());

        set.add(f1);
        set.add(f2);

        System.out.println(set.size());
        ArrayList ar = new ArrayList();

        Iterator it1 =set.iterator();
        while(it1.hasNext()){
            SampleFile sf = (SampleFile)it1.next();
            ar.add(sf);
        }

        Collections.sort(ar,  new Comparator<SampleFile>() {
	    public int compare(SampleFile s1, SampleFile s2) {
		return s1.getFileDate().compareTo(s2.getFileDate());
	    }}) ;

        for(int j=0; j<ar.size(); j++){
            SampleFile sf = (SampleFile)ar.get(j);
            System.out.println(sf.getFileName());
        }



}

}

class SampleFile {
String fileName;
java.util.Date fileDate;

    SampleFile(String name, java.util.Date d){
        fileDate = d;
        fileName = name;
    }

public java.util.Date getFileDate(){
    return fileDate;
}

public String getFileName(){
    return fileName;
}


}

Open in new window


Output:
2
a
b

Open in new window

0
 
LVL 47

Accepted Solution

by:
for_yan earned 1036 total points
ID: 35813502
OK. this is the ultimate experiment with many files
witn the same dates and different dates.
Everything seesm tio work fine (see ouput below):

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

public class SortedFiles {

    public static void main(String [] args){


        SimpleDateFormat ff = new SimpleDateFormat("MM-dd-yyyy");


        HashSet set = new HashSet();

        SampleFile f1 = new SampleFile("a", new java.util.Date());

         SampleFile f2 = new SampleFile("b", new java.util.Date());

        SampleFile f3 = new SampleFile("c", ff.parse("03-01-2011", new ParsePosition(0)));

        SampleFile f4 = new SampleFile("d", ff.parse("03-15-2011", new ParsePosition(0)));

         SampleFile f5 = new SampleFile("e", ff.parse("03-15-2011", new ParsePosition(0)));

         SampleFile f6 = new SampleFile("f", ff.parse("04-11-2011", new ParsePosition(0)));




        set.add(f1);
        set.add(f2);
        set.add(f3);
        set.add(f4);
        set.add(f5);
         set.add(f6);

        System.out.println(set.size());
        ArrayList ar = new ArrayList();

        Iterator it1 =set.iterator();
        while(it1.hasNext()){
            SampleFile sf = (SampleFile)it1.next();
            ar.add(sf);
        }

        Collections.sort(ar,  new Comparator<SampleFile>() {
	    public int compare(SampleFile s1, SampleFile s2) {
		return s1.getFileDate().compareTo(s2.getFileDate());
	    }}) ;

        for(int j=0; j<ar.size(); j++){
            SampleFile sf = (SampleFile)ar.get(j);
            System.out.println(sf.getFileName() + " " + sf.getFileDate().toString());
        }



}

}

class SampleFile {
String fileName;
java.util.Date fileDate;

    SampleFile(String name, java.util.Date d){
        fileDate = d;
        fileName = name;
    }

public java.util.Date getFileDate(){
    return fileDate;
}

public String getFileName(){
    return fileName;
}


}

Open in new window


Output:

6
c Tue Mar 01 00:00:00 PST 2011
d Tue Mar 15 00:00:00 PDT 2011
e Tue Mar 15 00:00:00 PDT 2011
f Mon Apr 11 00:00:00 PDT 2011
b Sun May 22 22:06:10 PDT 2011
a Sun May 22 22:06:10 PDT 2011

Open in new window

0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813537
You were right with being cautious about TreeSet.
I was thinking that it should use this Comapartor which we defined
only for establishing order. In fact it looks like it was using it for
add method aslo, and add method for TreeSet adds
element only if it is different from all other elements.
So when I was adding two files with different names but with the same date
it was not adding the second one as it was violating
that TereeSet should have all unique elements.
As a result I got the set with only one element.
Even when I overrode equals() explicitly in the Sample File class
that it should be equal only when all fields are equal, not just date, it still
was not adding the second object with the same date.
So probably with ArrayList, which does not have such issues,
it is much safer in such cases.
0
 

Author Comment

by:heyday2004
ID: 35813544
Many thanks. This works. So for sorted set, if the compare method returns 0, then even the hash code is different, the two records will be considered duplicate? Thanks.
0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 1036 total points
ID: 35813568
Probably. They have some words in the API, but these words sound a little bit ambiguous
So when I wrote my first message I went there and when I read those words, then I decided
to experuiment  and then realized that my initial understanding was not correct.

These are the words in
http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.


0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35814535
>>Please advise if this is true when we used SortedSet (based on the running result, it seems to be true). Thanks!

Yes, it is true. Something odd going on which i can't explain at the moment:

http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html#add(E)

Looking at the docs above, i was surprised that the equals method wasn't even called on my test SampleFile object
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 788 total points
ID: 35815079
I now understand the problem: the TreeSet example can't (at least easily - i'd like to be able to force it, but can't see a way at the moment) be used because the Comparator is 'not consistent with equals' (see docs for Comparator)

The easy solution - use a List with the same Comparator
0
 

Author Comment

by:heyday2004
ID: 35867869
Thanks for the excellent replies, I really appreciate it.
0
 

Author Closing Comment

by:heyday2004
ID: 35867871
Thanks!
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
Suggested Courses
Course of the Month9 days, 9 hours left to enroll

609 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question