Getting the max occurences of each individual number from a HashMap<Integer, List<Integer>>

Csongi Nagy :

I've been dealing with an exercise, in which I have to find a solution for the following problem: I have a

HashMap<Integer, List<Integer>>

and I have to get a List containing each of the elements of all of the lists in the HashMap with the maximum number of occurrences in any of the lists. So let's suppose my HashMap has got the following entries:

25, [30,30,2]

7, [2, 2, 2]

8, [8, 30]

In this case, I should somehow get a List with the following elements: [2, 2, 2, 8, 30, 30], because the maximum occurrences of each of the numbers are:

  • in the case of 2 it's 3 (in the value 7)
  • in the case of 8 it's 1 (in the value 8)
  • in the case of 30 it's 2 (in the value 25)

I am trying to use streams to do so, and I've written the following code:

map.entrySet()
            .stream()
            .map(Map.Entry::getValue)
            .collect(Collectors.toList());

This gets the individual lists, but what I need is to get one list, containing all the elements in any of the lists, with the maximum number of times it was mentioned. The order of the elements does not matter at all.

Please ask me if you need some clarification.

Thanks for your help in advance.

Andreas :

You can it like this:

static List<Integer> maxOccurrence(Map<Integer, List<Integer>> input) {
    return input.values().stream()
        .flatMap(list -> list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream())
        .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.maxBy(Comparator.naturalOrder()))))
        .entrySet().stream().sorted(Map.Entry.comparingByKey())
        .flatMap(e -> LongStream.range(0, e.getValue().get()).mapToObj(x -> e.getKey()))
        .collect(Collectors.toList());
}

Test

System.out.println(maxOccurrence(Map.of(
        25, List.of(30, 30, 2),
        7, List.of(2, 2, 2),
        8, List.of(8, 30))));

Output

[2, 2, 2, 8, 30, 30]

Explained

  1. Stream the values, i.e. the lists:

    input.values().stream()
    
    [8, 30]
    [2, 2, 2]
    [30, 30, 2]
    
  2. Count the occurrences of each value in each list:

    .flatMap(list -> list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream())
    
    8=1
    30=1
    2=3
    30=2
    2=1
    
  3. For each number, pick the highest occurrence:

    .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.maxBy(Comparator.naturalOrder()))))
    
    {8=1, 2=3, 30=2}
    
  4. Stream that sorted by number (key):

    .entrySet().stream().sorted(Map.Entry.comparingByKey())
    
    2=3
    8=1
    30=2
    
  5. Repeat each number by the occurrence:

    .flatMap(e -> LongStream.range(0, e.getValue().get()).mapToObj(x -> e.getKey()))
    
    2
    2
    2
    8
    30
    30
    
  6. Build a list with the result:

    .collect(Collectors.toList())
    
    [2, 2, 2, 8, 30, 30]
    

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=114458&siteId=1