Sorting java list by items in sublist

I have a list:

List<List<Item>> = [["a", "one", 3], ["b", "one", 2], ["c", "one", 4], ["d", "two", 2],["e", "one", 1], ["f", "two", 1]]

      

And I would like to sort it by the second value in the subarray, if there are two types, then it should sort by the third value, and if it finds two types from there, then it should sort them by the first element. So the end result should look like this:

[["e", "one", 1], ["b", "one", 2], ["a", "one", 3], ["c", "one", 4], ["f", "two", 1], ["d", "two", 2]]

      

Can anyone show me a good way to do this?

Thank!

+3


source to share


4 answers


["a", "one", 3]

should be an instance of your class like

class Item{
    private String val1;
    private String val2;
    private int val3;
    //getters and setters
}

      

So your list will be List<Item>

. Now you can just use Collections.sort(list, yourComparator)

or use Java 8 list.sort(yourComparator)

.

As yourComparator

you can pass an instance of a class that implements the interface Comparator

, for example, in the way



Comparator<Item> yourComparator = new Comparator<Item>() {

    @Override
    public int compare(Item o1, Item o2) {
        //comapre val2
        int result = o1.getVal2().compareTo(o2.getVal2());
        if (result != 0) return result;

        //if we are here val2 in both objects ware equal (result was 0)
        result = Integer.compare(o1.getVal3(), o2.getVal3());
        if (result != 0) return result;

        return o1.getVal1().compareTo(o2.getVal1());
    }
};

      

But a probably more readable and arguably simpler approach is to create separate comparators for each field and combine them. If you are using Java 8 your code might look like this:

Comparator<Item> val1Comparator = Comparator.comparing(Item::getVal1);
Comparator<Item> val2Comparator = Comparator.comparing(Item::getVal2);
Comparator<Item> val3Comparator = Comparator.comparingInt(Item::getVal3);


list.sort(val2Comparator
        .thenComparing(val3Comparator)
        .thenComparing(val1Comparator));

      

+3


source


Is there a good way to do this? Not what you think. The list of lists is too primitive; The list of custom objects will be better.



Write custom Comparators for the cases you want to run.

+2


source


Assuming "one"

less "two"

(since "o" < "t"

) and I don't see any other "string numbers" * here, one can simply write a simple comparator:

Comparator<List<Item>> c = new Comparator<List<Item>>() {

    int[] order = new int[]{1, 2, 0};  // order to compare: 2nd, then 3rd, finally 1st

    @Override
    public int compare(List<Item> l1, List<Item> l2) {
        for (int i = 0; i < order.length - 1; i++) {  
           int result = l1.get(i).compareTo(l2.get(i));
           if (result != 0)   // means that i-th elements are not the same
               return result;
        }
        return l1.get(order.length - 1).compareTo(l2.get(order.length - 1));
    }
}

      

Then sort with this comparator:

Collections.sort(list, c);

      


* For other "string numbers" such as "three", "four", etc., if you need to compare them meaningfully and not lexically, you will need to define a special collation that converts its "value" "to Integer

But that is beyond the scope of this question; submit a new one so that programmers not busy so busy practice coding at dummy speed.

+2


source


As duffymo suggests, use a list of objects. A simple structure would do:

class Triple implements Comparable<Triple> {
    Item first;
    Item second;
    Item third;

    int compareTo(Triple other) {
        int second = compare(this.second, other.second);
        if (second == 0) {
            int third = compare(this.third, other.third);
            if (third == 0) {
                return compare(this.first, other.first);
            }
            return third;
        }
        return second;
    }

    static int compare(Item lhs, Item rhs) {
        /* Do your compare here! */
    }
}
List<Triple> list;

      

Since struct implements Comparable, you can just sort: no need for a comparator.

Collections.sort(list);

      

0


source







All Articles