8

I have a Class1

public class Class1 {
    public Class(String s, int[] s1, int soc) {
       this.s = s;
       this.s1 = s1;
       this.soc = soc
    }
}

I have a List of Class1 (List<Class1>). I want to sort this list by soc, to get the Class1 with highest soc first

y2p
  • 4,791
  • 10
  • 40
  • 56
  • Do you have any stipulations? Does it need to be a recursive method or something of high-efficiency (e.g. quicksort)? Or are you looking for an easy/simple implementation. You could ultimately use a for() loop, however, it would be very difficult for the computer to do this if you have a list of, say, 100,000 items. – RageD Oct 25 '10 at 19:29
  • possible duplicate of [sort a List from highest to lowest](http://stackoverflow.com/questions/4017728/sort-a-listtuple-from-highest-to-lowest) – Fred Foo Oct 25 '10 at 19:34
  • Not a dup... if he asked it there he would have been changing his original question into a different one. – TofuBeer Oct 25 '10 at 20:53

4 Answers4

19

Use a Comparator

Collections.sort(list, new Comparator<Class1>() {
  public int compare(Class1 c1, Class1 c2) {
    if (c1.soc > c2.soc) return -1;
    if (c1.soc < c2.soc) return 1;
    return 0;
  }});

(Note that the compare method returns -1 for "first argument comes first in the sorted list", 0 for "they're equally ordered" and 1 for the "first argument comes second in the sorted list", and the list is modified by the sort method)

Scott Stanchfield
  • 29,742
  • 9
  • 47
  • 65
  • 4
    Won't work if one Class1 object has soc = Integer.MIN_VALUE for instance. – aioobe Oct 25 '10 at 19:34
  • 1
    Code fixed now. Previous version (return c2.soc - c1.soc) had some cases where it wouldn't work, for example if c2.soc is 2,000,000,000 and c1.soc is -1,000,000,000. "Nearly All Binary Searches and Mergesorts are Broken" - http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html – Julius Musseau Oct 25 '10 at 19:49
  • Thanks for the catch, aioobe and Julius! – Scott Stanchfield Oct 25 '10 at 19:58
1

Here is a complete example:

import java.util.*;

class Class1 {
    String s;
    int[] s1;
    int soc;

    public Class1(String s, int[] s1, int soc) {
       this.s = s;
       this.s1 = s1;
       this.soc = soc;
    }

    public String toString() { return String.format("s: %s   soc: %d", s, soc); }
}

public class Test {
    public static void main(String... args) {
        List<Class1> list = new ArrayList<Class1>();
        list.add(new Class1("abcd", new int[] {1}, 3));
        list.add(new Class1("efgh", new int[] {2}, 5));
        list.add(new Class1("ijkl", new int[] {8}, 9));
        list.add(new Class1("mnop", new int[] {3}, 7));

        Collections.sort(list, new Comparator<Class1>() {
            public int compare(Class1 o1, Class1 o2) {
                return o1.soc > o2.soc ? -1 : o1.soc == o2.soc ? 0 : 1;
            }
        });

        System.out.println(list.toString().replaceAll(",", "\n"));
    }
}

It prints the following:

[s: ijkl   soc: 9
 s: mnop   soc: 7
 s: efgh   soc: 5
 s: abcd   soc: 3]
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • Does `s`, `s1`, `soc`, really need to be default access instead of private? – Steve Kuo Oct 25 '10 at 19:42
  • If they're private, they would need to have accessor methods for the comparator to do its work (unless Class1 implemented Comparable, and you don't specify a Comparator) – Scott Stanchfield Oct 25 '10 at 19:47
0

Create a class that implements Comparator, create your custom sorting method and then pass an instance of that class into this function: Collections.sort

MattC
  • 12,285
  • 10
  • 54
  • 78
  • Example: Add getters and setters and you can use `this.list.sort(Comparator.comparing(Class1::getSoc));` – Christian Dec 18 '17 at 22:53
0

While Scott Stanchfield's answer is generally the easiest way to do this in Java currently, if you have other functional things you might want to do with properties of your class it can be useful to make use of Guava's Functions.

public class Class1 {
  ...
  public static final Function<Class1, Integer> GET_SOC =
      new Function<Class1, Integer>() {
        public Integer apply(Class1 input) {
          return input.soc;
        }
      };
  ...
}

Then you can use its Ordering class to sort:

 List<Class1> list = ...;
 Collections.sort(list, Ordering.natural().reverse().onResultOf(Class1.GET_SOC));

This uses the reverse of the natural ordering based on the soc property of each Class1 instance to give the ordering you want.

ColinD
  • 108,630
  • 30
  • 201
  • 202