Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How-to chain and apply a stream of comparators?

I have a stream of unsorted items and a stream of comparators. I want to apply all the comparators onto the stream by using "thenComparing" (Multisort) Is there a more elegant way than the following code to achive this?

Stream unsorted = ...;
Stream<Comparator> comparators = ...;

Comparator compareFunc = comparators.reduce(null, (a, b) -> {
        if(a == null) {
            return b;
        }else {
            return  a.thenComparing(b); 
        }

    });

Stream result = unsorted.sorted(compareFunc);
like image 367
jack Avatar asked Sep 15 '14 14:09

jack


People also ask

What is the difference between sorted stream and comparator comparator?

Stream sorted (Comparator comparator) returns a stream consisting of the elements of this stream, sorted according to the provided Comparator. For ordered streams, the sort method is stable but for unordered streams, no stability is guaranteed. It is a stateful intermediate operation i.e, it may incorporate state from previously seen elements ...

How to instantiate comparator in Java 8?

In java 8, Comparator can be instantiated using lambda expression. We can also reverse the natural ordering as well as ordering provided by Comparator. Stream< T > sorted (Comparator<? super T > comparator) Where, Stream is an interface and T is the type of stream elements. comparator is used to compare stream elements.

What is comparator in swift stream?

Stream< T > sorted (Comparator<? super T > comparator) Where, Stream is an interface and T is the type of stream elements. comparator is used to compare stream elements. Below given are some examples to understand the implementation of the function in a better way.

How to sort a list using comparator in Java 8?

Sorting a list in Java 8 is very easy with inbuilt support for comparators chaining. You created independent field sorter by implementing Comparator interface, and the chain them in Collection.sort () method.


2 Answers

Don’t use an identity value for Comparators. If the comparators stream is empty (i.e. does not contain any Comparator) you should not sort:

Stream result=comparators.reduce(Comparator::thenComparing)
             .map(unsorted::sorted).orElse(unsorted);

Note that if the comparators stream contains only a single Comparator, that Comparator will be the result of the reduction.


The method reference passed to Optional.map might need some experience to get used to it. So it might be worth using the more verbose lambda syntax to show what’s going on there:

Stream<String> result=comparators.reduce(Comparator::thenComparing)
    .map((comparator) -> unsorted.sorted(comparator)).orElse(unsorted);

That’s a matter of programming style or personal preference and might change over time.

like image 171
Holger Avatar answered Oct 25 '22 07:10

Holger


Using Mark Peters' suggestion and mixing it with a method reference, you could write your comparator this way:

Comparator compareFunc = comparators.reduce((a, b) -> 0, Comparator::thenComparing);

Or stealing a bit from Holger instead:

Optional<Comparator> compareFunc = comparators.reduce(Comparator::thenComparing);
Stream<?> result = compareFunc.isPresent() ? result.sorted(compareFunc.get())
                                           : unsorted;
like image 28
assylias Avatar answered Oct 25 '22 07:10

assylias