48

I got an object Recipe that implements Comparable<Recipe> :

public int compareTo(Recipe otherRecipe) {
    return this.inputRecipeName.compareTo(otherRecipe.inputRecipeName);
}

I've done that so I'm able to sort the List alphabetically in the following method:

public static Collection<Recipe> getRecipes(){
    List<Recipe> recipes = new ArrayList<Recipe>(RECIPE_MAP.values());
    Collections.sort(recipes);
    return recipes;
}

But now, in a different method, lets call it getRecipesSort(), I want to sort the same list but numerically, comparing a variable that contains their ID. To make things worse, the ID field is of the type String.

How do I use Collections.sort() to perform the sorts in Java?

jww
  • 97,681
  • 90
  • 411
  • 885
jsfrocha
  • 1,812
  • 2
  • 21
  • 32
  • 1
    http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html – Brian Roach May 07 '13 at 18:02
  • 1
    @BrianRoach I'm sorry if I don't meet your requirements for answering. I know where the documentation is, I'm just looking for creative solutions, since I can't seem to find any. Down-voting was just purely ridiculous but oh well, frustration can't be explained. – jsfrocha May 07 '13 at 18:36

5 Answers5

63

Use this method Collections.sort(List,Comparator) . Implement a Comparator and pass it to Collections.sort().

class RecipeCompare implements Comparator<Recipe> {

    @Override
    public int compare(Recipe o1, Recipe o2) {
        // write comparison logic here like below , it's just a sample
        return o1.getID().compareTo(o2.getID());
    }
}

Then use the Comparator as

Collections.sort(recipes,new RecipeCompare());
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • Almost. The OP wants to compare based on the ID fields, which are Strings, but to compare them numerically. We don't know the range, but if they fit in ints then converting to int and comparing would work, otherwise an appropriate type would have to be chosen or a more complicated comparator written, but this is the right approach. – David Conrad May 07 '13 at 17:45
  • 2
    Actually, I kind of like the simplicity of this answer, it made me think how I'd do it, I'm working on it now. – jsfrocha May 07 '13 at 18:37
29

The answer given by NINCOMPOOP can be made simpler using Lambda Expressions:

Collections.sort(recipes, (Recipe r1, Recipe r2) ->
r1.getID().compareTo(r2.getID()));

Also introduced after Java 8 is the comparator construction methods in the Comparator interface. Using these, one can further reduce this to 1:

recipes.sort(comparingInt(Recipe::getId));

1 Bloch, J. Effective Java (3rd Edition). 2018. Item 42, p. 194.

WaterGenie
  • 119
  • 1
  • 9
Gyanesh Sharma
  • 481
  • 5
  • 4
7

Create a comparator which accepts the compare mode in its constructor and pass different modes for different scenarios based on your requirement

public class RecipeComparator implements Comparator<Recipe> {

public static final int COMPARE_BY_ID = 0;
public static final int COMPARE_BY_NAME = 1;

private int compare_mode = COMPARE_BY_NAME;

public RecipeComparator() {
}

public RecipeComparator(int compare_mode) {
    this.compare_mode = compare_mode;
}

@Override
public int compare(Recipe o1, Recipe o2) {
    switch (compare_mode) {
    case COMPARE_BY_ID:
        return o1.getId().compareTo(o2.getId());
    default:
        return o1.getInputRecipeName().compareTo(o2.getInputRecipeName());
    }
}

}

Actually for numbers you need to handle them separately check below

public static void main(String[] args) {
    String string1 = "1";
    String string2 = "2";
    String string11 = "11";

    System.out.println(string1.compareTo(string2)); 
    System.out.println(string2.compareTo(string11));// expected -1 returns 1
   // to compare numbers you actually need to do something like this

    int number2 = Integer.valueOf(string1);
    int number11 = Integer.valueOf(string11);

    int compareTo = number2 > number11 ? 1 : (number2 < number11 ? -1 : 0) ;
    System.out.println(compareTo);// prints -1
}
threadfin
  • 116
  • 3
3

Use the method that accepts a Comparator when you want to sort in something other than natural order.

Collections.sort(List, Comparator)

John B
  • 32,493
  • 6
  • 77
  • 98
0

Sort the unsorted hashmap in ascending order.

// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) 
{
                return o2.getValue().compareTo(o1.getValue());
        }
    });

    // Maintaining insertion order with the help of LinkedList
    Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
    for (Entry<String, Integer> entry : list) {
        sortedMap.put(entry.getKey(), entry.getValue());
    }
Kashan
  • 906
  • 10
  • 15