Home > other >  To use streams to find keys in a list with max occurance
To use streams to find keys in a list with max occurance

Time:08-31

We have a list:

List<String> strList = Arrays.asList("10.0 string1", "10.3 string2", "10.0 string3", "10.4 string4","10.3 string5");

each entry is a string made of 2 strings separated by space. Objective is to find all the entries with max number of occurance (i.e 10.0 and 10.3 wit 2 occurrences).

The following code works. Question is could these 3 statements be reduced to 1 or at least 2?

var map2 = strList.stream()
                  .map(m -> {String[] parts = m.split(" "); return parts[0];})
                  .collect((Collectors.groupingBy(Function.identity(),LinkedHashMap::new, Collectors.counting())));

var max3 = map2.entrySet().stream()
               .max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1) 
               .get() 
               .getValue();

var listOfMax2 = map2.entrySet().stream()
                     .filter(entry -> entry.getValue() == max3)
                     .map(Map.Entry::getKey)
                     .collect(Collectors.toList());

System.out.println(listOfMax2);

CodePudding user response:

The code you have is pretty straight forward if you change the names of your variables to something meaningfull. You could write a custom collector, but i doubt it is worth the effort and is able to make your code much more readable. The easiest solution I can think of is, if you insists in chaining your stream, to first build the frequency and then invert the map to use the values(frequencies) as key and keys as value and to collect to a Treemap, which is sorted by key, and get the last entry:

List<String> strList = Arrays.asList("10.0 string1", "10.3 string2", "10.0 string3", "10.4 string4", "10.3 string5");

var mostFrequentEntries =
        strList.stream()
               .map(s -> s.substring(0, s.indexOf(' ')))
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
               .entrySet()
               .stream()
               .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
               .lastEntry().getValue();

System.out.println(mostFrequentEntries);

CodePudding user response:

strList
    .stream()
    .map(s -> s.substring(0, s.indexOf(" ")))
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
    .entrySet()
    .stream()
    .collect(Collectors.groupingBy(Entry::getValue))
    .entrySet()
    .stream()
    .max(Entry.comparingByKey())
    .ifPresent(opt -> System.out.println(opt.getValue()));

Fairly straightforward:

  1. Get the key using .map.
  2. Get the frequency of the key as a Map using .groupingBy.
  3. Group all the same frequencies together.
  4. Get the max frequency and print the List in O(n) time.
  • Related