Lets say I want to sort objects in an ArrayList
on a field height
in reversed order and if two values are the same I want to further sort on the field width also in reversed order. Is there a way by using something like
Comparator<Test> comparator = Comparator
.comparingInt((Test t) -> t.height).reversed()
.thenComparingInt((Test t ) -> t.width).reversed();
I know I could use something like:
Collections.sort(list, new Comparator<Test>() {
public int compare(Test o1, Test o2) {
Integer x1 = o1.height;
Integer x2 = o2.height;
int sComp = x2.compareTo(x1);
if (sComp != 0) {
return sComp;
}
x1 = o1.width;
x2 = o2.width;
return x2.compareTo(x1);
}});
But I'm really curious if there is one line solution
So regarding this mini-example
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
Test one = new Test();
one.height = 2;
one.width = 1;
Test two = new Test();
two.height = 2;
two.width = 3;
Test three = new Test();
three.height = 1;
three.width = 1;
Comparator<Test> comparator = Comparator
.comparingInt((Test t) -> t.height).reversed()
.thenComparingInt((Test t ) -> t.width).reversed();
List<Test> list = new ArrayList<>();
list.add(one);
list.add(two);
list.add(three);
list.stream()
.sorted(comparator)
.forEach(e -> System.out.println(e.height + "/" + e.width));
}
}
class Test {
int width;
int height;
}
I get the output:
1/1
2/3
2/1
because the second reversed()
reverses the whole list. Is there a way to gean a output of:
2/3
2/1
1/1
just remove reversed()
from comparingInt
and only call reversed
upon thenComparingLong
:
Comparator<Test> comparator =
Comparator.comparingInt((Test t) -> t.height) // <--- removed reverse from this comparator
.thenComparingLong((Test t ) -> t.width).reversed();
Further, given that width
is an int
I'd use thenComparingInt
instead of thenComparingLong
.
In addition, in regard to your stream pipeline, I'd suggest using forEachOrdered
since you care about the order in which the elements are printed.
forEach
is documented as:
The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.
Therefore:
list.stream()
.sorted(comparator)
.forEachOrdered(e -> System.out.println(e.height + "/" + e.width));