This is not like Collections.sort() where the parameter reference gets sorted. In this case you just get a sorted stream that you need to collect and assign to another variable eventually:
List result = list.stream().sorted((o1, o2)->o1.getItem().getValue().
compareTo(o2.getItem().getValue())).
collect(Collectors.toList());
You've just missed to assign the result
Answer from Jan B. on Stack OverflowThis is not like Collections.sort() where the parameter reference gets sorted. In this case you just get a sorted stream that you need to collect and assign to another variable eventually:
List result = list.stream().sorted((o1, o2)->o1.getItem().getValue().
compareTo(o2.getItem().getValue())).
collect(Collectors.toList());
You've just missed to assign the result
Use list.sort instead:
list.sort((o1, o2) -> o1.getItem().getValue().compareTo(o2.getItem().getValue()));
and make it more succinct using Comparator.comparing:
list.sort(Comparator.comparing(o -> o.getItem().getValue()));
After either of these, list itself will be sorted.
Your issue is that
list.stream.sorted returns the sorted data, it doesn't sort in place as you're expecting.
The following will sort the foos and the bars for each foo, but since the peek operation is mutating f, this will have unexpected behaviour if parallelism is involved.
List<Foo> foosSorted = foos.stream()
.sorted(Comparator.comparingInt(o -> o.sort))
.peek(f -> {
f.bars = f.bars.stream().sorted(Comparator.comparingInt(o -> o.sort)).collect(Collectors.toList());
})
.collect(Collectors.toList());
What I suggest is for you to add a constructor of Foo taking sort and bars and use map instead of peek. This way, we are not mutating any Foo object, so this can be run in parallel without trouble.
List<Foo> foosSorted = foos.stream()
.sorted(Comparator.comparingInt(o -> o.sort))
.map(f -> {
return new Foo(f.sort, f.bars.stream().sorted(Comparator.comparingInt(o -> o.sort)).collect(Collectors.toList()));
})
.collect(Collectors.toList());
with:
class Foo {
public int sort;
public List<Bar> bars;
public Foo(int sort) {
this.sort = sort;
}
public Foo(int sort, List<Bar> bars) {
this.sort = sort;
this.bars = new ArrayList<>(bars);
}
}
List<Foo> foosSort = foos.stream()
.sorted((o1, o2) -> (o1.sort - o2.sort))
.map(f -> {
List<Bar> bars = f.bars.stream()
.sorted((o1, o2) -> (o1.sort- o2.sort))
.collect(Collectors.toList());
f.bars = bars;
return f;
})
.collect(Collectors.toList());
Videos
You can use lambda expression in Comparator.comparing instead of method reference
List<Foo> res = foos.stream()
.sorted(Comparator.comparing(fo->fo.getSelect().getFooKey()))
.collect(Collectors.toList());
For just sorting you don't even need stream
foos.sort(Comparator.comparing(fo->fo.getSelect().getFooKey()));
Remove the map. The map changes the object in the stream. Update the sorted statement as
.sorted(Comparator.comparing(f -> f.getSelect().getFoosKey()))
This is the part of the code that causes an error
Sell::getClient.name
Your can create a reference to a (static or non-static) method of an arbitrary object of a particular type. A reference to the getClient method of any object of Sell type looks like this :
Sell::getClient
But method references are not objects and don't have members to access. With this code you are trying to access a member variable of the reference (and can't)
Sell::getClient.name
Also, method references are not classes so you can't get another method reference from them. You couldn't do something like that if you tried :
Sell::getClient::getName
Correct syntax for your particular case was provided by @mlk :
x -> x.getClient().nameSell::getClientName(doesn't have to be a static method)
In order to access the nested property and sort in reversed order, I am doing as:
Comparator<Sell> comparator = Comparator.comparing(h -> h.getAudit().getCreatedTs());
sells.sort(comparator.reversed());