sandy
sandy

Reputation: 123

Collectors.groupingBy() returns result sorted in ascending order java

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.

Upvotes: 7

Views: 18035

Answers (6)

uma mahesh
uma mahesh

Reputation: 124

 Map<String, List<TargetVaRResponsePTF>> statusMap = ptfDetails.stream().collect(Collectors.groupingBy(item -> {
      if (item.getStatus().equalsIgnoreCase("closed") && !item.isHasError()) {
        return "Completed";
      } else if (item.getStatus().equalsIgnoreCase("closed") && item.isHasError()) {
        return "CompletedWithError";
      } else if (item.getStatus().equalsIgnoreCase("running")) {
        return "Running";
      } else if (item.getStatus().equalsIgnoreCase("waiting")) {
        return "Waiting";
      } else if (item.getStatus().equalsIgnoreCase("error")) {
        return "Error";
      }
      System.out.println("none");
      return "none";
    }, ConcurrentHashMap::new, Collectors.toList()));

Upvotes: 0

papadave
papadave

Reputation: 21

There is an example in Collectors groupingby method javadoc. which u can use TreeMap to sort the result.

 Map<City, Set<String>> namesByCity
 *   = people.stream().collect(
 *     groupingBy(Person::getCity,
 *                TreeMap::new,
 *                mapping(Person::getLastName,
 *                        toSet())));

so i think u can try this following code.

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

Upvotes: 0

Mohammadreza  Alagheband
Mohammadreza Alagheband

Reputation: 2230

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.

Upvotes: 17

Mark Jeronimus
Mark Jeronimus

Reputation: 9543

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.

Upvotes: 4

Eugene
Eugene

Reputation: 120858

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()     

))

Upvotes: 9

drowny
drowny

Reputation: 2147

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

Upvotes: 0

Related Questions