-2

Here is my data set.

public class StudentData {

    public static List<Student> getData() {
        //student id,name,std, and hobbies
        return Arrays.asList(new Student(1, "a1", 1, Arrays.asList("cricket", "football", "basketball")),
                new Student(2, "a2", 1, Arrays.asList("chess", "football")),
                new Student(3, "a3", 2, Arrays.asList("running")),
                new Student(4, "a4", 2, Arrays.asList("throwball", "football")),
                new Student(5, "a5", 3, Arrays.asList("cricket", "basketball")),
                new Student(6, "a6", 4, Arrays.asList("cricket")), new Student(7, "a7", 5, Arrays.asList("basketball")),
                new Student(8, "a8", 6, Arrays.asList("football")),
                new Student(9, "a9", 8, Arrays.asList("tennis", "swimming")),
                new Student(10, "a10", 8, Arrays.asList("boxing", "running")),
                new Student(11, "a11", 9, Arrays.asList("cricket", "football")),
                new Student(12, "a12", 11, Arrays.asList("tennis", "shuttle")),
                new Student(13, "a13", 12, Arrays.asList("swimming")));
    }

}

From data set , i am finding , how many student based on hobbies and display the value in asc/desc order. For example : cricket ,4 and swimming: 2 and so on.
here is the code for group by hoppies .

Map<String, Integer> collect8 = data.stream()
                .flatMap(x -> x.getHobbies().stream().map(y -> new SimpleEntry<>(y, x)))
                .collect(Collectors.groupingBy(Entry::getKey, Collectors.mapping(entry -> entry.getValue().getId(),
                        Collectors.reducing(0, (a, b) -> a + b))));

output of collect8 :{running=13, swimming=22, shuttle=12, throwball=4, basketball=13, chess=2, cricket=23, boxing=10, football=26, tennis=21}

After that i am doing asc sorting by value .

Map<String, Integer> collect9 = 
                collect8.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue()).
                collect(Collectors.toMap(e->e.getKey(), e->e.getValue()));
        System.out.println(collect9);

output of collect9 : {running=2, swimming=2, shuttle=1, throwball=1, basketball=3, chess=1, cricket=4, boxing=1, football=5, tennis=2}

1.it is not sorted and giving the same result.any idea?
2. i am writing separate code for sorting. is it possble to do in collect8 itself?

Learn Hadoop
  • 2,760
  • 8
  • 28
  • 60

1 Answers1

0

For the first question, Collectors.toMap() currently creates a HashMap, which has no ordering, so sorting the Stream has no impact on the final Map. If you create a LinkedHashMap instead, it will keep the insertion order.

Map<String, Integer> collect9 = 
                collect8.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue()).
                collect(Collectors.toMap(e->e.getKey(), e->e.getValue(),(v1,v2)->v2,LinkedHashMap::new));

As for doing the grouping and sorting in a single pipeline, I'm not aware of a way to achieve that. If the sorting done was by the key of the Map, you could have achieved it easily by generating a TreeMap in the first Stream's collect, but since you want to sort by the value, I can't see a way of doing that in a single Stream pipeline.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • thanks a lot.. working fine as expected. (v1,v2)-> v1 - what doesn't mean. it tried -> v2 also. it is giving the same output. why v1,v2? – Learn Hadoop May 18 '18 at 15:02
  • @LearnHadoop that's a combiner function that must be passed to the `toMap` collector if you want to use the variant that specifies the desired `Map` implementation. I arbitrarily chose (v1,v2)->v1, which means that if the collector encounters a duplicate key, it assigns to that key the first value found for that key. If there are no duplicate keys, (v1,v2)->v2 behaves exactly the same. – Eran May 18 '18 at 15:06