Reputation: 33
Greeting,
I have 2 objects :
I wrote this code:
public List<Petition> getTheMostSigned(long groupId){
List<Petition> petitionList = petitionPersistence.findByStatusAndGroupId(0,groupId);
_log.info("list avant getTheMostSigned size : "+petitionList.stream().map(petition -> petition.getSignataires().size()).collect(Collectors.toList()));
List<Petition> resultList = petitionList.stream()
.sorted(Comparator.comparingInt(petition -> petition.getSignataires().size()))
.sorted(Collections.reverseOrder())
.collect(Collectors.toList());
_log.info("list apres getTheMostSigned size : "+resultList.stream().map(petition -> petition.getSignataires().size()).collect(Collectors.toList()));
return resultList;
The getSignataires() return a List.
but the result wasn't what I expected :
2018-09-12 12:44:25.686 INFO [http-nio-8080-exec-10][PetitionLocalServiceImpl:390] list avant getTheMostSigned size : [0, 0, 400, 0, 3, 401, 5501]
2018-09-12 12:44:25.856 INFO [http-nio-8080-exec-10][PetitionLocalServiceImpl:396] list apres getTheMostSigned size : [5501, 401, 3, 0, 0, **400**, 0]
As you can see, the penultimate is not the good one. do you know why the Comparator isn't doing the job ?
Upvotes: 3
Views: 112
Reputation: 131526
The result is expected as you chain two sorts.
The first one (.sorted(Comparator.comparingInt(petition -> petition.getSignataires().size())
) sorts by the list field size). Then the second one (.sorted(Collections.reverseOrder())
) overwrites the first sort result as the last one sorts according to the reverse natural order of Petition
.
As you invoke the sort stream operation twice, broadly it is like if you had used this logical :
List<Petition> petitionList = ...;
// first sort
petitionList.sort(Comparator.comparingInt(petition -> petition.getSignataires().size());
// second sort
petitionList.sort(Collections.reversed());
What you need is defining a Comparator
instance that combines these constraints.
And from Java 8, you can create Comparator
s and combine them thanks essentially to .thenComparingXXX()
and .reversed()
methods.
So you could do :
.sorted(Comparator.comparingInt(petition -> petition.getSignataires().size())
.reversed()
)
Upvotes: 5
Reputation: 6178
Below is another way to do thing using Collection's other overloaded method which uses custom compactor
Comparator<Petition> cmp =
(Petition left, Petition right) ->
left.getSignataires().size() - right.getSignataires().size();
List<Petition> resultList = petitionList.stream()
.sorted(Collections.reverseOrder(cmp))
.collect(Collectors.toList());
Upvotes: 1
Reputation: 49656
You don't need two sorted
operations. They won't be combined to produce a resulting Comparator
.
The first constructs a Comparator<Integer>
for int size()
values, while the second ignores the previous call and applies its own Comparator<Petition>
(Comparator.<Petition>reverseOrder()
).
Comparator<Petition> reversedSignaturesSizeComparator
= Comparator.<Petition>comparingInt(p -> p.getSignataires().size()).reversed();
List<Petition> resultList = petitionList.stream()
.sorted(reversedSignaturesSizeComparator)
.collect(Collectors.toList());
Upvotes: 3