*
The moose likes Java in General and the fly likes Collections.sort() does not sort my ArrayList Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Collections.sort() does not sort my ArrayList" Watch "Collections.sort() does not sort my ArrayList" New topic
Author

Collections.sort() does not sort my ArrayList

M Burke
Ranch Hand

Joined: Jun 25, 2004
Posts: 388
I wonder why this is not working. I have an ArrayList I extracted from a Set, then I try to sort it in natural order. It's a collection of Strings. What am I missing here?

//forumMap is a TreeMap using a Map reference
Set keys = forumMap.keySet();
ArrayList lKeys = new ArrayList(keys);
Collections.sort(lKeys);
//lKeys is not sorted!
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

How do you know IKeys is not ordered? Can you show us a bit more of the code, like the place where you test IKeys for order?


Steve
Norm Radder
Ranch Hand

Joined: Aug 10, 2005
Posts: 685
What does the compareTo() method look like for the objects being sorted?
M Burke
Ranch Hand

Joined: Jun 25, 2004
Posts: 388
I can see in the Eclipse debugger that the strings are not sorted. The object type is Java String, so I assume I don't need a custom comparer.

The list reads like this...

Inventory
Sales
Energy
Operations
Trucks

And it remains unchanged after the sort()
Jelle Klap
Bartender

Joined: Mar 10, 2008
Posts: 1753
    
    7

Don't declare the TreeMap as a Map, but as a NavigableMap, that way you can retrieve a NavigableSet using the navigableKeySet() method.

Edit: Oh, I'm sorry, you're sorting a List. Nevermind.
[ August 22, 2008: Message edited by: Jelle Klap ]

Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

When you iterate over the list, are they sorted?
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

When I run similar code (see below) the Strings are sorted inside the Set - as the contract for TreeMap says they should be. Can you post exact code that
1) Generates the Map
2) Gets the List of Entries
3) Iterates over the List
that shows your problem?


[ August 22, 2008: Message edited by: Steve Luke ]
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 37907
    
  22
Originally posted by Steve Luke:
When I run similar code (see below) the Strings are sorted inside the Set - as the contract for TreeMap says they should be.
But your code only demonstrates sorting a List. What happens when you print the Set before the Collections.sort call? Of course you are sorting Strings which implement Comparable already.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

Originally posted by Campbell Ritchie:
But your code only demonstrates sorting a List. What happens when you print the Set before the Collections.sort call? Of course you are sorting Strings which implement Comparable already.


The Set is pre-sorted in ascending order, because it is coming from a TreeMap which is a SortedMap. The List will be pre-sorted as well, so there would be no need to do the Collections.sort. I ran the test to follow the OP's use-case but still get different results than he suggests in his posts.

Unless I am missing something, the code I provided is just like the code he says he is using.
M Burke
Ranch Hand

Joined: Jun 25, 2004
Posts: 388
Originally posted by Steve Luke:
When I run similar code (see below) the Strings are sorted inside the Set - as the contract for TreeMap says they should be. Can you post exact code that
1) Generates the Map
2) Gets the List of Entries
3) Iterates over the List
that shows your problem?



[ August 22, 2008: Message edited by: Steve Luke ]



Once thing that is different with my TreeMap (forumMap) does not contain a String as the contained type. But the key is a String.

When I construct my map, it looks like this, Forum is a custom object...

forumList = fDAO.refreshForumList(mbJDO);
if(forumList != null){
Iterator ix = forumList.iterator();
while(ix != null && ix.hasNext()){
Forum forum = (Forum) ix.next();
forumMap.put(forum.getStrForumName(), forum);
}
}
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

Originally posted by M Burke:
Once thing that is different with my TreeMap (forumMap) does not contain a String as the contained type.


Yeah I used a String cause I had to put something in there. Putting new Object() or any other non-null value will have the same effect (tested it with new Object()) because TreeMap is sorted on the keys (and later, you only pull out the keys into the list for sorting again).

Originally posted by M Burke:
But the key is a String.


That would be one of the first things I would double check. When you get the List of Keys, iterate over it displaying the Class of the value in the list.

As stated above, the values will be sorted in the Map. They will be sorted when the keys are pulled outs as a Set, and the Collections.sort will properly sort Strings because String implements Comparable.

I could conceive that the Set could have un-sorted data returned to the List if the Map is still being built while you do
ArrayList lKeys = new ArrayList(keys);
The Set is backed by the original Map, so changes in the Map are reflected in the Set. If these changes happen while the List is iterating the Set you are likely to see inconsistent data.

But the List will be a snap-shot of the Set, and any further changes in the Set (or Map) will not affect the List once it is made, and the Collections.sort will work on that snap shot.
M Burke
Ranch Hand

Joined: Jun 25, 2004
Posts: 388
Originally posted by Steve Luke:


That would be one of the first things I would double check. When you get the List of Keys, iterate over it displaying the Class of the value in the list.

As stated above, the values will be sorted in the Map. They will be sorted when the keys are pulled outs as a Set, and the Collections.sort will properly sort Strings because String implements Comparable.

I could conceive that the Set could have un-sorted data returned to the List if the Map is still being built while you do
ArrayList lKeys = new ArrayList(keys);
The Set is backed by the original Map, so changes in the Map are reflected in the Set. If these changes happen while the List is iterating the Set you are likely to see inconsistent data.

But the List will be a snap-shot of the Set, and any further changes in the Set (or Map) will not affect the List once it is made, and the Collections.sort will work on that snap shot.


I checked to be certain the keys are strings, and they are. I put some extra tests in my code to verify it. When I use a TreeMap that contains Strings as the data, then the sort works. But my TreeMap does npt sort.

When I run this, className is equal to "class java.lang.String"

Set keys = forumMap.keySet();
ArrayList aKeys = new ArrayList();
Iterator ix = keys.iterator();

while(ix != null && ix.hasNext()){
Object obj = ix.next();
Class c = obj.getClass();
String className = c.toString();
String tmp = new String(obj.toString());
aKeys.add(tmp);
}

Collections.sort(aKeys);

There is something about my TreeMap not using Strings as data that is messing thing up.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

Originally posted by M Burke:

There is something about my TreeMap not using Strings as data that is messing thing up.


That shouldn't be either. For example, if I use integers, or Person objects (a random immutable class I have sitting around) which I intentionally order in a different manner than the Strings natural ordering then the sort will still work.

The problem must be with the Strings being used as Keys, which are both causing the TreeMap not to sort and the Collection.sort not to work.

The natural order of Strings is case sensitive (example "Fred" comes before "adam" but after "Adam"), so case will influence order. Perhaps toUpperCase or toLowerCase all keys?
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

When I use a TreeMap that contains Strings as the data


Do you mean if you do:


Then the sorting works - using the same keys as the map that doesn't sort?
M Burke
Ranch Hand

Joined: Jun 25, 2004
Posts: 388
Well, I found the problem. It is sorting, just not as I expected. All the upper case strings sort in front of the lower case strings. So I has to add a compare to the original TreeMap so it sorts without regard to case.

Map forumMap = new TreeMap(new TwoStringComparatorIgnoreCase());

Using this custom class...

public class TwoStringComparatorIgnoreCase implements Comparator {

public int compare( Object object1, Object object2 ) {
return ((String) object1).compareToIgnoreCase((String) object2 );
}

}
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

Glad to see you got it working. I just wanted to comment about providing information regarding your problem. You had previously posted:

Originally posted by M Burke:
The list reads like this...

Inventory
Sales
Energy
Operations
Trucks

And it remains unchanged after the sort()


If you had shown real results than we would have been able to conclude the Case Sensitivity issue sooner.

So in the future, please provide Real Results when posting your questions.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Also, that comparator has been available in the standard Java API since Java 1.2. There's a static Comparator variable in the String class named "CASE_INSENSITIVE_ORDER" that you could have used:

(Not that writing code that duplicates standard API functions is a bad thing, it does provide useful experience. I'm sure I have done it in the past. But if I found I had done it, I would replace my code with a call to the standard API. The less code I have to maintain, the better.)
[ August 22, 2008: Message edited by: Paul Clapham ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Collections.sort() does not sort my ArrayList
 
Similar Threads
Code to sort and remove duplicates in ArrayList and Hashmap
Comparator
ArrayList Sorting Using Comparator? Exception at Runtime
CachedRowSet
Sorting two ArrayLists, one dependent on the other