Reputation: 137
I have list like this:
List<Integer> list = new ArrayList<>();
list.add(24);
list.add(12);
list.add(0);
list.add(36);
list.add(1);
list.add(99);
I want to sort it ascending, but 0 has to always be the last element. Is there any way to simplify it?
List<Integer> collect = list.stream()
.sorted((a,b) -> b.compareTo(a))
.sorted((a, b) -> Integer.valueOf(0).equals(a) ? 1 : -1)
.collect(Collectors.toList());
Upvotes: 1
Views: 123
Reputation: 21255
I would create a custom Comparator
that sorts the elements in the desired order, then pass that to Stream.sorted
:
Comparator<Integer> comparator = Comparator
.comparing((Integer i) -> i == 0 ? 1 : 0)
.thenComparing(Comparator.naturalOrder());
List<Integer> collect = list.stream().sorted(comparator).toList();
Comparator.comparing((Integer i) -> i == 0 ? 1 : 0)
treats 0 as greater than every other Integer
, and all other values as equal. The call to .thenComparing
then performs a tie-breaker comparison using the standard integer comparison in the case where the first comparison resulted in 0 (i.e. neither value was 0, or both values were 0).
Incidentally, having the Comparator
means that the list can be easily sorted in-place if you want to mutate it, rather than creating a copy using streams:
List<Integer> list = new ArrayList<>(List.of(24, 12, 0, 36, 1, 99));
list.sort(comparator);
Upvotes: 0
Reputation: 16498
May be introducing variables for the comparators and comparing the boolean if an int equals to zero might simplify or at least make it readable
Comparator<Integer> natural = Comparator.naturalOrder();
Comparator<Integer> zeroLast = Comparator.comparing(i -> i.equals(0));
List<Integer> collect = list.stream()
.sorted(natural)
.sorted(zeroLast)
.collect(Collectors.toList());
Upvotes: 0
Reputation: 1877
You can process in the same sorted
:
List<Integer> collect = list.stream()
.sorted((o1, o2) -> o1 == 0 ? 1 : (o2 == 0 ? -1 : o1.compareTo(o2)))
.collect(Collectors.toList());
Upvotes: 0
Reputation: 103273
List<Integer> list = List.of(24, 12, 0, 36, 1, 99);
List<Integer> sorted = list.stream()
.sorted(Comparator.comparingInt(a -> a == 0 ? Integer.MAX_VALUE : a))
.toList();
System.out.println(sorted);
Seems to work; prints [1, 12, 24, 36, 99, 0]
.
The one downside is that it won't do the right thing if literally the maximum integer value (which is 2147483647
) is in your list, in which case it'll sort the 0s amongst them instead of after them. If that is a problem, nothing is going to look significantly shorter than what you did.
NB: Your code appears to sort descending. In which case the 0 would already sort at the end unless you have negative numbers. If that's what you want and 'ascending' was a typo, you'd have to use MIN_VALUE instead, and reverse the comparator (tack .reverse()
t the end).
Upvotes: 2