Collectors.groupingBy() returns result sorted in a

2020-07-24 05:15发布

I am sending result in descending order but I get output with ascending order

List<myEntity> myData = new ArrayList<>();
Map<Integer,List<myEntity>> myid = new LinkedHashMap<>();

try {
    myData = myService.getData(id); 
    myid = myData.stream().collect(Collectors.groupingBy(myEntity::getDataId)); 

Here mydata is sorted by desc order but after creating collections by group data id my list get sorted with ascending order. I want my collection list to be descending order not ascending order.

4条回答
姐就是有狂的资本
2楼-- · 2020-07-24 05:48

As @Holger described in Java 8 is not maintaining the order while grouping , Collectors.groupingBy() returns a HashMap, which does not guarantee order.

Here is what you can do:

myid = myData.stream()
.collect(Collectors.groupingBy(MyEntity::getDataId,LinkedHashMap::new, toList()));

Would return a LinkedHashMap<Integer, List<MyEntity>>. The order will also be maintained as the list used by collector is ArrayList.

查看更多
【Aperson】
3楼-- · 2020-07-24 05:48

Collectors.groupingBy returns a HashMap without any order as such (as to why you see "some order" is explained here). The correct way to do this is to specify the Map that preserve the order inside the Collectors.groupingBy:

myData.stream()
      .collect(Collectors.groupingBy(
          MyEntity::getDataId,
          LinkedHashMap::new,
          Collectors.toList()     

))
查看更多
beautiful°
4楼-- · 2020-07-24 05:57

collect(Collectors.groupingBy()) returns a new Map which overwrites the variable to your previous LinkedHashMap. Your initial assignment is therefore futile. The exact type returned is undefined by the specs but in my test run it returned a HashMap. (Never assume this will always be the case across different versions and brands of Java!)

But the main issue is that you're storing Integer as keys. If the values of those keys is smaller than the modulus of the table inside the HashMap, they will just appear ordered (because the hashCode of an Integer is just it;s value). When I tested with 1000 Integer values of 0..999, the hashtable (the array as part of the inner workings of HashMap) appeared to be of size 2048. (Again, undocumented so don't assume it!)

In summary, the reason you see the results in ascending order is because of an implementation artifact, not because there's a specific reason.

查看更多
forever°为你锁心
5楼-- · 2020-07-24 06:01

You need reverse order of map. So In java 8 , i solved with this.

myData = myService.getData(id);
myid = myData.stream().collect(Collectors.groupingBy(myEntity::getDataId));

Map<Integer, List<myEntity>> finalMap = new LinkedHashMap<>();
myid.entrySet().stream()
        .sorted(Map.Entry.<Integer, List<myEntity>>comparingByKey()
                .reversed())
        .forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
System.out.println("FINAL RESULT : " + finalMap);

Entryset gives us Integers of this map of myid. So sort and get from first map which is myid and put in finalMap

查看更多
登录 后发表回答