Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Streams - Sort if Comparator exists

I have a class where optionally a Comparator can be specified.


Since the Comparator is optional, I have to evaluate its presence and execute the same stream code, either with sorted() or without:

if(comparator != null) {
    [...].stream().map()[...].sorted(comparator)[...];
} else {
    [...].stream().map()[...];
}

Question:
Is there a more elegant way to do this without the code duplication?

Note:
A default Comparator is not an option, I just want to keep the original order of the values I am streaming.

Besides, the elements are already mapped at the point of sorting, so I can not somehow reference the root list of the stream, as I do not have the original elements anymore.

like image 378
JDC Avatar asked Jul 27 '17 06:07

JDC


People also ask

How do I use Comparator in collections sort?

Using a comparator, we can sort the elements based on data members. For instance, it may be on roll no, name, age, or anything else. Method of Collections class for sorting List elements is used to sort the elements of List by the given comparator.

How do you sort a list of objects based on an attribute of the objects in Java?

sort() method to sort a list of objects using some examples. By default, the sort() method sorts a given list into ascending order (or natural order). We can use Collections. reverseOrder() method, which returns a Comparator, for reverse sorting.


4 Answers

You can do something like this:

Stream<Something> stream = [...].stream().map()[...]; // preliminary processing
if(comparator != null) {
    stream = stream.sorted(comparator); // optional sorting
}
stream... // resumed processing, which ends in some terminal operation (such as collect)
like image 169
Eran Avatar answered Sep 29 '22 14:09

Eran


Another way would be to use Optional:

Stream<Whatever> stream = [...].stream().map()[...];

List<WhateverElse> result = Optional.ofNullable(comparator)
    .map(stream::sorted)
    .orElse(stream)
    .[...] // <-- go on with the stream pipeline
    .collect(Collectors.toList());
like image 43
fps Avatar answered Sep 29 '22 14:09

fps


You could define a comparator of your type (I used E as a placeholder here) that will not change the order:

 Comparator<E> NO_SORTING = (one, other) -> 0;

If the comparator field is an Optional of Comparator, you can then use

.sorted(comparator.orElse(NO_SORTING))
like image 25
Boris van Katwijk Avatar answered Sep 29 '22 16:09

Boris van Katwijk


If you don't mind use third party library StreamEx

StreamEx(source).[...].chain(s -> comparator == null ? s : s.sorted(comparator)).[...];
like image 42
123-xyz Avatar answered Sep 29 '22 16:09

123-xyz