2

I have List of Double Array and I would like sort it according to first and last field. So far I am able to sort it by only 1 element of array.

Real state:

0         1         2
-------  -------  -------
78       100        0
78       100        1
0        100        0
104      100        1

Expected:

0         1         2
-------  -------  -------
0        100       0
78       100       1
78       100       0
101      100       1

I want to sort field according to value of 1st element of Array. If value of 1st and 2nd are equal I want to sort according to 3rd element where first should be 1 and then 0 (there will be only 1 and 0 value)

List<Double[]> splitList = new ArrayList<>();
Double[] tmp1 = { 78d, 100d, 0d };
Double[] tmp2 = { 78d, 100d, 1d };
Double[] tmp3 = { 0d, 100d, 0d };
Double[] tmp4 = { 104d, 100d, 1d };
splitList.add(tmp1);
splitList.add(tmp2);
splitList.add(tmp3);
splitList.add(tmp4);
splitList.sort(Comparator.comparingDouble(a -> a[0]));

This one sort me according to first element. I found solution to sort by two elements https://stackoverflow.com/a/26865122/9774735 so I tried it:

splitList.sort(Comparator.comparingDouble(a -> a[0]).thenComparingDouble(b -> b[2]));

and it output me an error:

Multiple markers at this line
    - The type of the expression must be an array type but it resolved 
     to Object
    - The type of the expression must be an array type but it resolved 

How can I compare List of Array?

3 Answers 3

5

Seems like the java compiler has problems in infering the generic type, you have some options to overcome this problem:

  1. Use type hints with the pattern Class.<GenericType>.method(Arguments):

    splitList.sort(Comparator.<Double[]>comparingDouble(a -> a[0]).thenComparingDouble(b -> b[2]));
    
  2. Declare the lambda parameter type (declaring it for the first seems to be enough):

    splitList.sort(Comparator.comparingDouble((Double[] a) -> a[0]).thenComparingDouble(b -> b[2]));
    

After reading your comments you want to reverse the last comparison, which can be done like this:

Comparator.<Double[]>comparingDouble(a -> a[0])
   .thenComparing(Comparator.<Double[]>comparingDouble(b -> b[2]).reversed())

Which is quite messy, you're better of using something like this:

splitList.sort((a, b) -> {
    int c = Double.compare(a[0], b[0]);
    return c == 0 ? Double.compare(b[2], a[2]) : c;
});
Sign up to request clarification or add additional context in comments.

1 Comment

I suppose that the 0 would be before 1 (Im talking about 3rd element). I want 1 to be first and then 0.
2

Try this:

    splitList.sort((a,b) -> {
        int r = a[0].compareTo(b[0]);
        if (r == 0) {
            r = a[2].compareTo(b[2]);
        }
        return r;
    });

Comments

1

If you use java 8 or next version you can use this:

splitList.stream()
            .sorted(Comparator.comparing((Double[] array) -> array[0])
                    .thenComparing(Comparator.comparing((Double[] array2) -> array2[2]).reversed()));

to print in console:

splitList.stream()
            .sorted(Comparator.comparing((Double[] array) -> array[0])
                    .thenComparing(Comparator.comparing((Double[] array2) -> array2[2]).reversed()))
            .forEach(array -> System.out.println(Arrays.toString(array)));

or you can collect in a list then can print the list too:

List<Double[]> list = splitList.stream()
            .sorted(Comparator.comparing((Double[] array) -> array[0])
                    .thenComparing(Comparator.comparing((Double[] array2) -> array2[2]).reversed()))
            .collect(Collectors.toList());

for (Double[] array: list) {
    System.out.println(Arrays.toString(array));
}

Best of luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.