views:

144

answers:

5

I have an ArrayList of video resolutions that looks like this:

"1024x768", "800x600", "1280x1024", etc

I want to sort it based on numeric value in first part of string. Ie, the above would sort out to look like this:

"800x600","1024x768","1280x1024"

Is there a quick and dirty way to do this, by that I mean in less then 2-3 lines of code? If not, what would be the proper way? The values I get are from an object not my own. It does have a getWidth() and getHeight() methods that return ints.

A: 

The proper way is to write a Comparator implementation that operates on Strings, except that it parses up to the first non-numeric character. It then creates an int out of that and compares the ints.

You can then pass an instance of that Comparator into Collections.sort() along with your List.

John Gaughan
A: 

Use a custom Comparator to sort the ArrayList via the Collections api.

Collections.sort(resolutionArrayList, new ResolutionComparator())
Tim Bender
A: 

Using a Comparator will work, but will get slow if you have lots of values because it will parse each String more than once.

An alternative is to add each value to a TreeMap, with the number you want as the key, i.e., Integer.valueOf(s.substring(0,s.indexOf('x'))), then create a new ArrayList from the sorted values in treeMap.values().

Carey
Reading for comprehension, I see you already have the parsed numbers, so my answer doesn’t really apply.
Carey
The List would have to be huge for Collections.sort() to get noticeably slow. And a fix could be for the comparator to cache the parsed number, so every String would only be parsed once.
seanizer
+4  A: 

If the objects in the array are Resolution instances with getWidth methods then you can use a Comparator to sort on those:

Collections.sort(resolutions, new Comparator {
    public int compare(Resolution r1, Resolution r2) {
        return Integer.valueOf(r1.getWidth()).compareTo(Integer.valueOf(r2.getWidth()));
    }
});
Shadwell
`Integer.valueOf()` would have been nicer than `new Integer()`, but still +1
seanizer
Comparators return a negative or positive integer or zero, so you can return r1.getWidth() - r2.getWidth() instead.
Carey
Updated to use Integer.valueOf - ta.
Shadwell
@Carey: Using subtractiondoes not handle overflow for very large inputs. That trick should only be used with an appropriate comment.
bkail
Hmm, yes. That would be an interesting bug to try to find. I see that Java 7 will have a convenient Integer.compare(x,y) method, which would be easy to steal from http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/176586cd040e/src/share/classes/java/lang/Integer.java .
Carey
A: 

The solution suggested by Shadwell in his answer is correct and idiomatic.

But if you're looking for a more concise solution, then I'd advise you use lambdaj which will enable you to write code like:

List<Resolution> sortedResolutions = sort(resolutions, on(Resolution.class).getWidth());
missingfaktor