简体   繁体   中英

List within list Sorting issue in Java

I am trying to sort a List<List<Integer>> . The internal list will have 3 values. (X-coordinate, Y-coordinate, Start/end) Now while it works for most of the cases, the sorting fails for a specific case.

The code I used for sorting is:

arr.sort((a,b) -> {
            if(a.get(0)!=b.get(0)){
                return a.get(0) - b.get(0);
            }
            else{
                return  (a.get(2)==0?-a.get(1):a.get(1)) - (b.get(2)==0?-b.get(1):b.get(1));
            }
        });

The logic behind it is: If x value is not equal we sort them on the basis of x. if equal then: if both start then on basis of height in descending order. if both end then on basis of height in ascending order. else whichever was the start.

The start is shown as 0 and end as 1.

The example in which is failing is: arr:

[[1, 10000, 0], [10001, 10000, 1], [2, 9999, 0], [10001, 9999, 1]]

Output:

[[1, 10000, 0], [2, 9999, 0], [10001, 10000, 1], [10001, 9999, 1]]

while the expected sorting is:

[[1, 10000, 0], [2, 9999, 0], [10001, 9999, 1], [10001, 10000, 1]]

Can you please help me find out what I am doing wrong?

The code is working as intended. Since in your code for the comparison between [10001, 9999, 1] and [10001, 10000, 1] , it will go in the else statement and since a.get(2) and b.get(2) both are non zero, the else statement will be reduced to b.get(1) - a.get(1) , which sorts in descending order. Therefore, it will sort in the order [10001, 10000, 1] and then [10001, 9999, 1] .

Also, boxed integers ( Integer ) should not be compared using == or != operators as they will be compared by reference. Instead, equals method should be used.

The second else condition should subtract y of b from y of a. Something like this:

(a,b) -> {
        if(!a.get(0).equals(b.get(0))){
            return a.get(0) - b.get(0);
        }
        else{
            return (a.get(2).equals(0)?-a.get(1):a.get(1)) - (b.get(2).equals(0)?-b.get(1):b.get(1));
        }
    }

I think the original sort code is very hard to read and don't match your expectation. I change it to:

public static void main(String[] args) {
        List<List<Integer>> list = Arrays.asList(Arrays.asList(1, 10000, 0),
                Arrays.asList(10001, 10000, 1), Arrays.asList(2, 9999, 0)
        ,Arrays.asList(10001, 9999, 1)
        , Arrays.asList(10001, 9999, 0));

        Collections.sort(list, (a,b) -> {
            if(!a.get(0).equals(b.get(0))){
                return a.get(0) - b.get(0);
            }
            else{
                if (b.get(2).equals(a.get(2))) {
                    if (a.get(2) == 0) {
                        return Integer.compare(b.get(1), a.get(1)); //start, descending
                    } else {
                        return Integer.compare(a.get(1), b.get(1)); // ascending
                    }
                } else {
                    return  a.get(2) == 0 ? -1 : 1; // 0 first
                }
            }
        });

        System.out.println(list); // [[1, 10000, 0], [2, 9999, 0], [10001, 9999, 0], [10001, 9999, 1], [10001, 10000, 1]]

    }

Hope it helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM