patternjavaMinor
Find the rarest in a map
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)
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.