13

I am calling the sorted method on a stream. And the java doc says:

"Sorted method returns a stream consisting of the elements of this stream, sorted according to natural order."

But when I run the code below:

List<String> list = new ArrayList<String>();
list.add("b");
list.add("a");
list.add("z");
list.add("p");
list.stream().sorted();
System.out.println(list);

I am getting output as

[b, a, z, p]

Why am I not getting the output of a natural sort?

Sartorius
  • 499
  • 5
  • 12
saurabh suman
  • 161
  • 1
  • 1
  • 8
  • 1
    sorted() returns a stream with the elements sorted, it doesn't sort your current stream. – Derrops Oct 10 '16 at 03:14
  • @Snickers3192: you meant “it doesn’t sort the `List`” as there is no “current stream”. Naming things that wrong leads to exactly the confusion, the OP has shown. – Holger Oct 10 '16 at 15:03
  • @Holger Sorry yeah replace stream with list. – Derrops Oct 10 '16 at 23:20

4 Answers4

15

Change this

list.stream().sorted();
System.out.println(list);

to something like

list.stream().sorted().forEachOrdered(System.out::println);

Your method is println the list (not the sorted stream). Alternatively (or additionally), you could shorten your initialization routine and re-collect the List like

List<String> list = new ArrayList<>(Arrays.asList("b","a","z","p"));
list = list.stream().sorted().collect(Collectors.toList());
System.out.println(list);

Which outputs (as you probably expected)

[a, b, p, z]
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 3
    I think you mean `forEachOrdered`, not `forEach`. – Louis Wasserman Oct 10 '16 at 06:21
  • There is no reason to copy the result of `Arrays.asList` to an `ArrayList`; the method `Arrays.asList` returns a `List`. In either case, the list is mutable and doesn’t need a stream detour like `list = list.stream().sorted().collect(Collectors.toList());` a simple `list.sort(null);` will sort the list in-place. – Holger Oct 10 '16 at 15:05
7

You should collect the result of the sorting and then assign it to your list.

    List<String> list = new ArrayList<String>();
    list.add("b");
    list.add("a");
    list.add("z");
    list.add("p");
    list = list.stream().sorted().collect(Collectors.toList());
    System.out.println(list);
iamorozov
  • 761
  • 7
  • 26
5

If you want to have your sorted list.

Let's change this

list.stream().sorted();

to

list.sort((e1, e2) -> e1.compareTo(e2));

Hope this help!

David Pham
  • 1,673
  • 19
  • 17
  • unfortunately, this is not a acceptable answer. Because, the OP's way is indeed correct. You don't need to pass a custom comparator in order to get the natural ordering for a given stream of string objects. BTW; above 2 answers will point what has went wrong. Hope you could learn something from it :) – Jude Niroshan Oct 10 '16 at 05:23
  • @Jude: do you know the difference between calling `list.stream().sorted()` and calling `list.sort(…)`? The custom comparator might be obsolete, still, this answer is correct. – Holger Oct 10 '16 at 15:09
  • 1
    @Holger hi, the 1st one will just sort the elements in natural order. *(using compareTo or obj.toString().compareTo() implementations)*. Ohh, man... It's a new default method added from Java 8 to List interface. Sorry, my bad. But, this answer, doesn't point out the fact that intermediate operations won't fire unless having a terminal operation. – Jude Niroshan Oct 11 '16 at 01:06
  • 1
    @Jude: even with a terminal operation, stream operations do not modify the source list. Yes, this answer lacks explanations, but provides a straight-forward solution. Though, I’d prefer `list.sort(null)` or `list.sort(Comparator.naturalOrder())`… – Holger Oct 11 '16 at 09:07
  • @Holger yes. `Comparator.naturalOrder()` is to the point. – Jude Niroshan Oct 11 '16 at 09:16
4

Your stream has no terminal operator, and therefore is not processed. Terminal operators include but are not limited to: forEach, toArray, reduce, collect. Your code segment should be similar to

list.stream().sorted().forEachOrdered(System.out::println);