How can I sort a vector of my custom object and choose which property to sort by?
I did see this question & answer but I'm not too sure what its sorting it based on. Code example would be prefered to "methodology".
Sort a Vector of custom objects
public class ItemLocation {
String icon;
String title;
String message;
String subtext;
String deviceId;
double latCoords;
double lngCoords;
int expiary;
int id;
double proximity;
String locSeen;
}
Below is a example that will allow you to sort by a specified field of ItemLocation:
public void sort(final String field, List<ItemLocation> itemLocationList) {
Collections.sort(itemLocationList, new Comparator<ItemLocation>() {
@Override
public int compare(ItemLocation o1, ItemLocation o2) {
if(field.equals("icon")) {
return o1.icon.compareTo(o2.icon);
} if(field.equals("title")) {
return o1.title.compareTo(o2.title);
} else if(field.equals("message")) {
return o1.message.compareTo(o2.message);
}
.
. fill in the rest of the fields...
.
else if(field.equals("locSeen")) {
return o1.locSeen.compareTo(o2.locSeen);
}
}
});
}
See the JavaDocs for java.util.Comparable
and java.util.Comparator
.
A class that implements Comparable
can be compared against other instances of that class. This is useful to implement a natural search order. To allow ordering other than the class's natural order you would need to implement a Comparator
. A Comparator
is a separate object that is capable of comparing two other objects using whatever criteria it wants.
In your case you'd probably want to implement a Comparator
for each of the different properties that you want to order by, or one that can be configured.
Comparable
and Comparator
both use the same idea to determine ordering: A method returns less than 0, 0, or greater than 0 to inform the caller which of the 2 objects is ordered first. In the case of Comparable
the first object is this
.
This one works:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* ComparableDemo
* @author Michael
* @since 2/24/11
*/
public class ComparableDemo
{
public static void main(String[] args)
{
List<ItemLocation> itemLocations = new ArrayList<ItemLocation>();
for (String arg : args)
{
itemLocations.add(new ItemLocation(arg));
}
System.out.println("before sort: " + itemLocations);
Comparator<ItemLocation> comparator = new ItemLocationComparator();
Collections.sort(itemLocations, comparator);
System.out.println("after sort: " + itemLocations);
}
}
class ItemLocation
{
String icon;
String title;
String message;
String subtext;
String deviceId;
double latCoords;
double lngCoords;
int expiary;
int id;
double proximity;
String locSeen;
ItemLocation(String message)
{
this("", "", message, "", "", 0.0, 0.0, 0, 0, 0.0, "");
}
ItemLocation(String icon, String title, String message, String subtext, String deviceId, double latCoords, double lngCoords, int expiary, int id, double proximity, String locSeen)
{
this.icon = icon;
this.title = title;
this.message = message;
this.subtext = subtext;
this.deviceId = deviceId;
this.latCoords = latCoords;
this.lngCoords = lngCoords;
this.expiary = expiary;
this.id = id;
this.proximity = proximity;
this.locSeen = locSeen;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append("ItemLocation");
sb.append("{message='").append(message).append('\'');
sb.append('}');
return sb.toString();
}
}
class ItemLocationComparator implements Comparator<ItemLocation>
{
public int compare(ItemLocation o1, ItemLocation o2)
{
return o1.message.compareTo(o2.message);
}
}
Here's the output:
C:\JDKs\jdk1.6.0_21\bin\java -Didea.launcher.port=7534 "-Didea.launcher.bin.path=C:\Program Files\JetBrains\IntelliJ IDEA 10.0.2\bin" -Dfile.encoding=windows-1252 com.intellij.rt.execution.application.AppMain ComparableDemo zeb meme apple
before sort: [ItemLocation{message='zeb'}, ItemLocation{message='meme'}, ItemLocation{message='apple'}]
after sort: [ItemLocation{message='apple'}, ItemLocation{message='meme'}, ItemLocation{message='zeb'}]
Process finished with exit code 0
Let's say we have a class with an int and a string. I can define how one object of that class may be compared against other.
I could choose any criteria. For instance, I may decide to sort based on the int. If I happen to have two int's with the same value, I may decide the string as an additional criteria, something like this:
// this class *knows* how to "compare" against him self
class CustomObject implements Comparable<CustomObject> {
String aString;
int aInt;
...
public int compareTo(CustomObject two ) {
int diff = this.aInt - two.aInt;//<-- compare ints
if( diff != 0 ) { // they have different int
return diff;
}
return this.aString.compareTo( two.aString );//<-- compare strings...
}
...
}
Here's a complete running demo ...
import java.util.*;
class SortDemo {
public static void main( String ... args ) {
// create a bunch and sort them
List<CustomObject> list = Arrays.asList(
new CustomObject(3, "Blah"),
new CustomObject(30, "Bar"),
new CustomObject(1, "Zzz"),
new CustomObject(1, "Aaa")
);
System.out.println( "before: "+ list );
Collections.sort( list );
System.out.println( "after : "+ list );
}
}
// this class *knows* how to "compare" against him self
class CustomObject implements Comparable<CustomObject> {
String aString;
int aInt;
CustomObject( int i, String s ) {
aInt = i;
aString = s;
}
// comparable interface lets you
// specify "HOW" to compare two
// custom objects
public int compareTo(CustomObject two ) {
// I migth compare them using the int first
// and if they're the same, use the string...
int diff = this.aInt - two.aInt;
if( diff != 0 ) { // they have different int
return diff;
}
// else let the strings compare them selves
return this.aString.compareTo( two.aString );
}
public String toString(){
return "CustomObject[aInt="+aInt+", aString="+aString+"]";
}
}
Here's the output:
before: [CustomObject[aInt=3, aString=Blah], CustomObject[aInt=30, aString=Bar], CustomObject[aInt=1, aString=Zzz], CustomObject[aInt=1, aString=Aaa]]
after : [CustomObject[aInt=1, aString=Aaa], CustomObject[aInt=1, aString=Zzz], CustomObject[aInt=3, aString=Blah], CustomObject[aInt=30, aString=Bar]]
I hope that's clear enough
You can also pass a custom comparator. Let me know if you need a sample of that.