Alex Wittig
Alex Wittig

Reputation: 2900

multiple .sorted(...) calls on java 8 stream

I have a Stream of objects that I want to sort naturally, but also force one of the members to always be first.

For example:

List<String> result = Stream.of("a", "s", "d", "f")
        .sorted(Comparator.comparing((String s) -> !s.equals("d"))
                            .thenComparing(Comparator.naturalOrder()))
        .collect(toList());
System.out.println(result);

This produces

[d, a, f, s]

That is, alphabetical but with "d" first.

I noticed that I can also write this using multiple .sorted(...) calls:

List<String> result = Stream.of("a", "s", "d", "f")
        .sorted()
        .sorted(Comparator.comparing(s -> !s.equals("d")))
        .collect(toList());
System.out.println(result);

This produces the same result, and is IMO more readable.

However, I don't see examples of anyone else doing it this way.

Furthermore, IntelliJ IDEA flags the first .sorted() call as redundant. It says the "subsequent 'sorted' call makes sorting useless".

This is demonstrably untrue, as removing the call changes the output to

[d, a, s, f]

So my question is: are multiple .sorted(...) calls on a Stream defined behavior, or am I just getting lucky?

In other words, is this a supported use of .sorted() that I can depend on, or does it only happen to work now and might stop working in some future release of Java?

Upvotes: 6

Views: 2393

Answers (1)

Ousmane D.
Ousmane D.

Reputation: 56453

When you say "defined", I am assuming you're asking "is the sort stable"? if so then yes it's.

The first sorted() call of the second example snippet will sort the elements according to the natural order and then sorts again according to the provided comparator.

The issue with the second approach is that it's inefficient as it requires two sorting operations, for that reason one may decide to proceed with the first approach.

Upvotes: 4

Related Questions