borjab borjab - 1 year ago 67
Java Question

Sort a java stream with a non-total ordering criteria.

I am trying to create a method that sorts a List by making:

private List<Processor> getByPriority(){
return new ProcessorComparator() ).collect( Collectors.toList() );

But I read in the Comprator javadoc that compare to needs to be a total ordering relation. That is, no two comparator may have the same priority unless they are equal. This might not be the case.

I was trying this simple comparator:

public class ProcessorComparator implements Comparator<TTYMessageProcessor<?>>{

public int compare( Processor processor1 , Processor processor2 ) {
return processor1.getPriority() - processor2.getPriority();

Of course I could make the Processor Comparable but I would like to avoid modifications to all the Proccessors. Isn't there any way to sort them with streams? As alternatives I could write my own method or create a more complex comparator but I am surprised of the lack of a more elegant solution.

Answer Source

Reading the references the elements of the original stream are preserved:

Returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.

No elements will be evicted, deleted or duplicated. The same elements come out of the sort as go in, just re-ordered.

Edit: the docs also state for

It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is "Note: this comparator imposes orderings that are inconsistent with equals."

This may introduce confusion about equals when used in maps or sets:

Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals to order a sorted set (or sorted map). Suppose a sorted set (or sorted map) with an explicit comparator c is used with elements (or keys) drawn from a set S. If the ordering imposed by c on S is inconsistent with equals, the sorted set (or sorted map) will behave "strangely." In particular the sorted set (or sorted map) will violate the general contract for set (or map), which is defined in terms of equals.

The confusion is lifted if you think about Comparator as an abstraction of the key-value pair: you wouldn't expect two pairs to be equal in case their keys were equal. It just means that some property of those values (i.e. their keys) is considered alike.