HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Find the rarest in a map

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
maptherarestfind

Problem

Write a method rarest that accepts a map whose keys are strings and
whose values are integers as a parameter and returns the integer value
that occurs the fewest times in the map. If there is a tie, return the
smaller integer value. If the map is empty, throw an exception.

For example, suppose the map contains mappings from students' names
(strings) to their ages (integers). Your method would return the least
frequently occurring age. Consider a map variable m containing the
following key/value pairs:

{Alyssa=22, Char=25, Dan=25, Jeff=20, Kasey=20, Kim=20, Mogran=25,
Ryan=25, Stef=22}

Three people are age 20 (Jeff, Kasey, and Kim), two
people are age 22 (Alyssa and Stef), and four people are age 25 (Char,
Dan, Mogran, and Ryan).

So a call of rarest(m) returns 22 because only
two people are that age. If there is a tie (two or more rarest ages
that occur the same number of times), return the youngest age among
them. For example, if we added another pair of Kelly=22 to the map
above, there would now be a tie of three people of age 20 (Jeff,
Kasey, Kim) and three people of age 22 (Alyssa, Kelly, Stef). So a
call of rarest(m) would now return 20 because 20 is the smaller of the
rarest values.

Here is the link to the question.

```
public int rarest(Map m)throws Exception{
    if(m.size() == 0){
      throw new Exception();//throwing an exception as per the question
    }else{
    Integer count = null;
//Creating a TreeMap to get the lowest age.
    TreeMap t = new TreeMap();
    for(Map.Entry me : m.entrySet()){
        if(t.containsKey(me.getValue())) {
            count = t.get(me.getValue());
            t.put(me.getValue(), count+1);
        }else {
            count = 1;
            t.put(me.getValue(), count);
        }
      }  
        
     //If there is tie I am comparing the frequencies   
     int freq = t.get(t.firstKey());

     TreeSet val = new TreeSet();

     for(Integer i : t.keySet()){
        if(freq > t.get(i) ){
            freq = t.get(i)

Solution

This is more efficient than the accepted answer. min is O(1) memory and O(n) time while sorted is O(n) memory and O(n*log(n)) time:

import static java.util.Comparator.comparingLong;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

Comparator> byRarity = comparingLong(Map.Entry::getValue);
Comparator> byAge = comparingInt(Map.Entry::getKey);

int rarest = data.values().stream()
        .collect(groupingBy(x->x, counting()))
        .entrySet().stream()
        .min(byRarity.thenComparing(byAge))
        .get()        // or throw if map is empty
        .getKey();

Code Snippets

import static java.util.Comparator.comparingLong;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;


Comparator<Map.Entry<Integer, Long>> byRarity = comparingLong(Map.Entry::getValue);
Comparator<Map.Entry<Integer, Long>> byAge = comparingInt(Map.Entry::getKey);

int rarest = data.values().stream()
        .collect(groupingBy(x->x, counting()))
        .entrySet().stream()
        .min(byRarity.thenComparing(byAge))
        .get()        // or throw if map is empty
        .getKey();

Context

StackExchange Code Review Q#101796, answer score: 6

Revisions (0)

No revisions yet.