Missing value in a TreeMap after putAll() - java

I have a HashMap that map character to an Integer. In order to sort it by value I wrote my comparator and I'm using TreeMap. But I am missing the value. I checked that for String "tree". My map 'chars' after for each loop looks like {r=1, t=1, e=2} and tree after putAll (two lines later) is {e=2, r=1}. What is happening to char 't'? Why is it missed? And how can I change it?
class ValueComparator implements Comparator<Character> {
private Map<Character, Integer> map;
public ValueComparator(Map<Character, Integer> map) {
this.map = map;
}
public int compare(Character a, Character b) {
return map.get(b).compareTo(map.get(a));
}
}
public String frequencySort(String s) {
if (s.length() <= 1) return s;
HashMap<Character,Integer> chars = new HashMap<Character,Integer>();
for(Character c : s.toCharArray()){
if (chars.containsKey(c)){
chars.put(c,chars.get(c)+1);
}
else {
chars.put(c,1);
}
}
TreeMap<Character,Integer> tree = new TreeMap<Character,Integer>(new ValueComparator(chars));
tree.putAll(chars);
/**
* rest of the code
**/
}

Your ValueComparator treats entries with the same count as duplicates. A simple fix is to use the key as a tie-breaker:
public int compare(Character a, Character b) {
int result = map.get(b).compareTo(map.get(a));
return result != 0 ? result : a.compareTo(b);
}
Alternatively, you can use streams to build the frequency map, sort it and store it an ordered LinkedHashMap:
Map<Character, Integer> counts = s.chars()
.mapToObj(i -> (char)i)
.collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(c -> 1)))
.entrySet()
.stream()
.sorted(Collections.reverseOrder(Entry.comparingByValue()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new));

Related

How to use Map.merge for incrementing the counter as value?

I am trying to refactor a method that counts keys in HashMap in a more efficient way by implementing Map.merge(). How can I achieve it on the following code:
public Map<Character, Integer> countCharacterUsage(String input) {
Map<Character, Integer> characterToCountUsage = new WeakHashMap<>();
for (char symbol : input.toCharArray()) {
if (characterToCountUsage.containsKey(symbol)) {
int symbolsCount = characterToCountUsage.get(symbol);
characterToCountUsage.put(symbol, ++symbolsCount);
} else {
characterToCountUsage.put(symbol, 1);
}
}
return characterToCountUsage;
}
You can use compute
characterToCountUsage.compute(symbol, (k,v)-> v==null ? 1 : v+1);
Also with merge
characterToCountUsage.merge(symbol,1, (k,v)-> v+1);

Sort after values in an Object inside HashMap

I had to code my own ´Filter` for a medal table, which I put in a
HashMap <String, MedalsOfCountry> unsortedList.
The key is the code of a country, for example:"USA" and the MedalsOfCountry is the object for the specific country with the fields: goldCount, silverCount, bronzeCount. MedalsOfCountry is a static inner class, which I coded and looks like this:
static class MedalsOfCountry extends Filter {
int goldCount;
int silverCount;
int bronzeCount;
Medal medalType;
MedalsOfCountry(Medal m, int count) {
medalType = m;
if (medalType == Medal.GOLD) {
goldCount += count;
} else if (medalType == Medal.SILVER) {
silverCount+= count;
} else {
bronzeCount += count;
}
}
public int compareTo(MedalOfCountry medals) {
if(this.goldCount == medals.goldCount) {
return this.silverCount - medals.silverCount;
} else if(this.silverCount == medals.silverCount) {
return this.bronzeCount - medals.bronzeCount;
}
return this.goldCount - medals.goldCount;
}
Anyway I tried to sort my HashMap like this:
Map<String, MedalsOfCountry> sortedList = new TreeMap<String, MedalsOfCountry>(new Comparator<String>() {
#Override
public int compare(String land1, String land2) {
return unsortedList.get(land1).compareTo(unsortedList.get(land2));
}
Why does my sorting not work?
A TreeMap is sorted by keys:
The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
So using a TreeMap would not be the best choice in your case. You could either use a LinkedHashMap or changing your map to a List.
A LinkedHashMap is sorted by insertion order:
This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
Map<String, MedalsOfCountry> sorted = unsorted.entrySet().stream()
.sorted((entry0, entry1) -> entry0.getValue().compareTo(entry1.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v0, v1) -> {
throw new IllegalArgumentException("duplicate keys are not possible here");
}, LinkedHashMap::new));
To improve this I would recommend to implement the Comparable interface in your Object class:
static class MedalsOfCountry implements Comparable<MedalsOfCountry> {
int goldCount;
int silverCount;
int bronzeCount;
MedalsOfCountry(int count) {
goldCount += count;
}
#Override
public int compareTo(MedalsOfCountry medals) {
int compareGold = this.goldCount - medals.goldCount;
if (compareGold != 0) {
return compareGold;
}
int compareSilver = this.silverCount - medals.silverCount;
if (compareSilver != 0) {
return compareSilver;
}
return this.bronzeCount - medals.bronzeCount;
}
}
You then can use the following to create the sorted map:
Map<String, MedalsOfCountry> sorted = unsorted.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getValue))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v0, v1) -> {
throw new IllegalArgumentException("duplicate keys are not possible here");
}, LinkedHashMap::new));
Additionally you can improve your compareTo() method by using a comparator to define multiple steps:
#Override
public int compareTo(MedalsOfCountry medals) {
return Comparator.comparingInt(MedalsOfCountry::getGoldCount)
.thenComparingInt(MedalsOfCountry::getSilverCount)
.thenComparingInt(MedalsOfCountry::getBronzeCount)
.compare(this, medals);
}
To also can use the Comparator.reversed() method to reverse the order of your stream:
Map<String, MedalsOfCountry> sorted = unsorted.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry<String, MedalsOfCountry>::getValue).reversed())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v0, v1) -> {
throw new IllegalArgumentException("duplicate keys are not possible here");
}, LinkedHashMap::new));

Most frequent element stream

How to find most frequent element, but when there are few most frequent element return null.
I would like to find code equivalent of:
public static void main(String[] args) {
System.out.println("Should return A -> " + mostFrequent(Arrays.asList("A", "A", "B")));
System.out.println("Should null as element in list have same frequency -> "
+ mostFrequent(Arrays.asList("A", "B")));
}
private static String mostFrequent(List<String> elements) {
Map<String, Long> ordered = new TreeMap<>();
for (String e : elements) {
if (!ordered.containsKey(e)) {
ordered.put(e, 0L);
}
Long tmp = ordered.get(e);
ordered.put(e, ++tmp);
}
String mostFrequent = null;
long i = 0;
Iterator<Map.Entry<String, Long>> it = ordered.entrySet().iterator();
while (it.hasNext() && i < 2) {
Map.Entry<String, Long> pair = it.next();
if (i == 0) {
mostFrequent = pair.getKey();
} else {
if (ordered.get(mostFrequent) == ordered.get(pair.getKey())) {
return null;
}
}
i++;
}
return mostFrequent;
}
However stream version does not handle most frequent elements with the same frequency.
private static String mostFrequentStream(List<String> elements) {
return elements.stream()
.reduce(BinaryOperator.maxBy(
Comparator.comparingInt(o -> Collections.frequency(elements, o))))
.orElse(null);
}
How to modify stream above to achieve it?
using groupingBy:
String mostFrequentStream(List<String> elements) {
Map<String, Long> temp = elements.stream()
.collect(Collectors.groupingBy(a -> a, Collectors.counting()));
return new HashSet<>(temp.values()).size() < temp.size() ?
null : temp.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey).get();
}
I managed to build a concatenated Stream but it got long:
private static String mostFrequentStream3(List<String> elements) {
return elements.stream() // part 1
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream() // part 2
.collect(Collectors.groupingBy(Entry::getValue))
.entrySet().stream() // part 3
.max(Entry.comparingByKey())
.map(Entry::getValue)
.filter(v -> v.size() == 1)
.map(v -> v.get(0).getKey())
.orElse(null);
}
To "find most frequent element, but when there are few most frequent element return null"
Part 1 counts the frequency of every element.
Part 2 groups entries by frequency.
Part 3 looks up the entry with the highest frequency. If this entry does only have one element ("there are few most frequent"), then it's the one and only maximum. Otherwise null is returned.
I would never use stream for this to avoid hurting readability and performance at the same time. For the sake of fun -
private static String mostFrequentStream(List<String> elements) {
Map<String, Long> frequencyMap = elements.stream().collect(groupingBy(Function.identity(), counting()));
return frequencyMap.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(2).reduce((i, e) -> i.getValue().equals(e.getValue()) ? new AbstractMap.SimpleEntry<>(null, 0L) : i).get().getKey();
}

Why does HashMap auto-sort character-type keys, though being an unordered collection?

I created a small code example in order to demonstrate the difference of HashMap and TreeMap.
public class HashMapSimpleValueAutosort {
private static final char[] alphabet = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
public static void main(String[] args) {
Map<Character, Integer> map = new HashMap<>();
inverseAbc(map, "HashMap");
map = new TreeMap<>();
inverseAbc(map, "TreeMap");
}
private static void inverseAbc(Map<Character, Integer> map, String desc ) {
System.out.println(desc);
for (int i=25; i>=0; --i) {
map.put(alphabet[i], 26 - i);
}
System.out.println(map);
}
}
What it does, is to assign the alphabet letters in the reverse order inside the map as keys and their position in the alphabet as the corresponding value, using a HashMap and a TreeMap approach.
Althought the keys are inserted in the inversed order, HashMap toString() outputs them in ascending order, just like TreeMap does.
So the question that arises here is:
Does toString() method of HashMap, sorts the keys internally before returning the string represention of the map ?
EDIT:
It seams that this might be a JDK or IDE based symptom and not restricted only to toString().
public class HashMapSimpleValueAutosort {
private static final char[] alphabet = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
public static void main(String[] args) {
Map<Character, Integer> map = new HashMap<>();
printEntries(map, "HashMap");
map = new TreeMap<>();
printEntries(map, "TreeMap");
}
private static void printEntries(Map<Character, Integer> map, String desc) {
System.out.println(desc);
for (int i=25; i>=0; --i) {
map.put(alphabet[i], 26 - i);
}
System.out.print("{ ");
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
System.out.printf("%c=%d,", entry.getKey(), entry.getValue());
}
System.out.println(" }");
}
}
In the example above I print the key-value pairs as entries.
This is a curious result of the implementation of HashMap.
A HashMap has to decide in which of the hash buckets to place the entry. It decides this based on the hashCode() of the key object. Now, hashCode() can be any integer at all. So it first does this to the hash code:
(h = key.hashCode()) ^ (h >>> 16)
Now, your key in this case is of type Character. The hashCode for Character is the value of the character itself. Java char is 16-bits wide. So shifting it 16 bits to the right will give you zero. Xoring it with that zero gives you the original value - the char value!
The values you have chosen are consecutive. This means that they will happen to be stored in the hash table buckets at indexes i, i+1, i+2...
This also happens to be the order at which the entry set iterator, on which toString is based, traverses that table: it goes through the table consecutively. So as long as you don't have collisions, for Character keys that happen to be consecutive, you'll see the result "sorted".
It is coincidence that HashMap appears sorted, which only occurs because the values are very simple.
If you change to String, and double the letters, such that hashCode() returns more complex values, the HashMap will appear more like what is usually expected: Order appears random (it's isn't, but might as well be).
private static final String[] alphabet = {"aa","bb","cc","dd","ee","ff","gg","hh","ii","jj","kk","ll","mm",
"nn","oo","pp","qq","rr","ss","tt","uu","vv","ww","xx","yy","zz"};
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
inverseAbc(map, "HashMap");
map = new TreeMap<>();
inverseAbc(map, "TreeMap");
}
private static void inverseAbc(Map<String, Integer> map, String desc ) {
System.out.println(desc);
for (int i=alphabet.length-1; i>=0; --i) {
map.put(alphabet[i], alphabet.length - i);
}
System.out.println(map);
}
Output
HashMap
{tt=7, zz=1, xx=3, vv=5, rr=9, pp=11, nn=13, ll=15, jj=17, hh=19, ff=21, dd=23, bb=25, ss=8, yy=2, ww=4, uu=6, qq=10, oo=12, mm=14, kk=16, ii=18, gg=20, ee=22, cc=24, aa=26}
TreeMap
{aa=26, bb=25, cc=24, dd=23, ee=22, ff=21, gg=20, hh=19, ii=18, jj=17, kk=16, ll=15, mm=14, nn=13, oo=12, pp=11, qq=10, rr=9, ss=8, tt=7, uu=6, vv=5, ww=4, xx=3, yy=2, zz=1}
First and foremost -
HashMap is not ordered collection.
TreeMap is ordered collection.
So, if you are expecting that you will put values in certain order in your HashMap and it will remain so then it is wrong. It is unordered collection. Also, I ran it my local and HashMap output was unordered and TreeMap was ordered
Like said above, TreeMap is an ordered collection and it works because when you put values in TreeMap then a Comparator is sorting them. See below TreeMap.put implementation.
While when you put values in HashMap then there is no such sorting.
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
Pre-Java8 v/s Java8:
Implementation of put method of HashMap in Java8 is different than Java7 or before, and it internally uses TreeNode and all, and is logic looks pretty different ... That could be the reason. Check Java8 HashMap.put here
HashMap, LinkedHashMap and TreeMap are the three most popular Map types.
LinkedHashMap maintains insertion order i.e elements are stored as they are inserted.
TreeMap stores the elements according to supplied Comparator or in the natural order, if you don’t supply any Comparator.
HashMap doesn’t guarantee any order.
So if you want the map to retain the insertion order, use LinkedHashMap
class Solution {
public int firstUniqChar(String s) {
char ch ;
Map<Character,Integer> map = new LinkedHashMap<Character,Integer>() ;
for(int i = 0; i < s.length(); i++)
{
ch = s.charAt(i) ;
map.put(ch,map.getOrDefault(ch,0)+1) ;
}
for(char key : map.keySet())
{
if(map.get(key) == 1)
return s.indexOf(key+"") ;
}
return -1 ;
}}

Finding Key associated with max Value in a Java Map

What is the easiest way to get key associated with the max value in a map?
I believe that Collections.max(someMap) will return the max Key, when you want the key that corresponds to the max value.
For completeness, here is a java-8 way of doing it
countMap.entrySet().stream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();
or
Collections.max(countMap.entrySet(), (entry1, entry2) -> entry1.getValue() - entry2.getValue()).getKey();
or
Collections.max(countMap.entrySet(), Comparator.comparingInt(Map.Entry::getValue)).getKey();
Basically you'd need to iterate over the map's entry set, remembering both the "currently known maximum" and the key associated with it. (Or just the entry containing both, of course.)
For example:
Map.Entry<Foo, Bar> maxEntry = null;
for (Map.Entry<Foo, Bar> entry : map.entrySet())
{
if (maxEntry == null || entry.getValue().compareTo(maxEntry.getValue()) > 0)
{
maxEntry = entry;
}
}
A simple one liner using Java-8
Key key = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
This code will print all the keys with maximum value
public class NewClass4 {
public static void main(String[] args)
{
HashMap<Integer,Integer>map=new HashMap<Integer, Integer>();
map.put(1, 50);
map.put(2, 60);
map.put(3, 30);
map.put(4, 60);
map.put(5, 60);
int maxValueInMap=(Collections.max(map.values())); // This will return max value in the HashMap
for (Entry<Integer, Integer> entry : map.entrySet()) { // Iterate through HashMap
if (entry.getValue()==maxValueInMap) {
System.out.println(entry.getKey()); // Print the key with max value
}
}
}
}
Here's how do do it directly (without an explicit extra loop) by defining the appropriate Comparator:
int keyOfMaxValue = Collections.max(
yourMap.entrySet(),
new Comparator<Entry<Double,Integer>>(){
#Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
return o1.getValue() > o2.getValue()? 1:-1;
}
}).getKey();
1. Using Stream
public <K, V extends Comparable<V>> V maxUsingStreamAndLambda(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max((Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue())
);
return maxEntry.get().getKey();
}
2. Using Collections.max() with a Lambda Expression
public <K, V extends Comparable<V>> V maxUsingCollectionsMaxAndLambda(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), (Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue()));
return maxEntry.getKey();
}
3. Using Stream with Method Reference
public <K, V extends Comparable<V>> V maxUsingStreamAndMethodReference(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max(Map.Entry.comparingByValue());
return maxEntry.get()
.getKey();
}
4. Using Collections.max()
public <K, V extends Comparable<V>> V maxUsingCollectionsMax(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), new Comparator<Entry<K, V>>() {
public int compare(Entry<K, V> e1, Entry<K, V> e2) {
return e1.getValue()
.compareTo(e2.getValue());
}
});
return maxEntry.getKey();
}
5. Using Simple Iteration
public <K, V extends Comparable<V>> V maxUsingIteration(Map<K, V> map) {
Map.Entry<K, V> maxEntry = null;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (maxEntry == null || entry.getValue()
.compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry.getKey();
}
An answer that returns an Optional since the map may have no max value if it is empty:
map.entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey);
I have two methods, using this méthod to get the key with the max value:
public static Entry<String, Integer> getMaxEntry(Map<String, Integer> map){
Entry<String, Integer> maxEntry = null;
Integer max = Collections.max(map.values());
for(Entry<String, Integer> entry : map.entrySet()) {
Integer value = entry.getValue();
if(null != value && max == value) {
maxEntry = entry;
}
}
return maxEntry;
}
As an example gettin the Entry with the max value using the method:
Map.Entry<String, Integer> maxEntry = getMaxEntry(map);
Using Java 8 we can get an object containing the max value:
Object maxEntry = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
System.out.println("maxEntry = " + maxEntry);
Simple to understand.
In Below code, maxKey is the key which is holding the max value.
int maxKey = 0;
int maxValue = 0;
for(int i : birds.keySet())
{
if(birds.get(i) > maxValue)
{
maxKey = i;
maxValue = birds.get(i);
}
}
Java 8 way to get all keys with max value.
Integer max = PROVIDED_MAP.entrySet()
.stream()
.max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1)
.get()
.getValue();
List listOfMax = PROVIDED_MAP.entrySet()
.stream()
.filter(entry -> entry.getValue() == max)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(listOfMax);
Also you can parallelize it by using parallelStream() instead of stream()
given map
HashMap abc = new HashMap<>();
get all map entries with a maximum of values.
you can use any of the below methods in the filter to get respective map entries for sets of minimum or maximum values
Collections.max(abc.values())
Collections.min(abc.values())
Collections.max(abc.keys())
Collections.max(abc.keys())
abc.entrySet().stream().filter(entry -> entry.getValue() == Collections.max(abc.values()))
if only want to get the keys for the filter map
abc.entrySet()
.stream()
.filter(entry -> entry.getValue() == Collections.max(abc.values()))
.map(Map.Entry::getKey);
if you want to get the values for the filtered map
abc.entrySet()
.stream()
.filter(entry -> entry.getValue() == Collections.max(abc.values()))
.map(Map.Entry::getvalue)
if you want to get all such keys in a list:
abc.entrySet()
.stream()
.filter(entry -> entry.getValue() == Collections.max(abc.values()))
.map(Map.Entry::getKey)
.collect(Collectors.toList())
if you want to get all such values in a list:
abc.entrySet()
.stream()
.filter(entry -> entry.getValue() == Collections.max(abc.values()))
.map(Map.Entry::getvalue)
.collect(Collectors.toList())
Is this solution ok?
int[] a = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7 };
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i : a) {
Integer count = map.get(i);
map.put(i, count != null ? count + 1 : 0);
}
Integer max = Collections.max(map.keySet());
System.out.println(max);
System.out.println(map);
int maxValue = 0;
int mKey = 0;
for(Integer key: map.keySet()){
if(map.get(key) > maxValue){
maxValue = map.get(key);
mKey = key;
}
}
System.out.println("Max Value " + maxValue + " is associated with " + mKey + " key");
Majority Element/ max element in the map :
public class Main {
public static void main(String[] args) {
int[] a = {1,3,4,3,4,3,2,3,3,3,3,3};
List<Integer> list = Arrays.stream(a).boxed().collect(Collectors.toList());
Map<Integer, Long> map = list.parallelStream()
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
System.out.println("Map => " + map);
//{1=1, 2=1, 3=8, 4=2}
map.entrySet()
.stream()
.max(Comparator.comparing(Entry::getValue))//compare the values and get the maximum value
.map(Entry::getKey)// get the key appearing maximum number of times
.ifPresentOrElse(System.out::println,() -> new RuntimeException("no such thing"));
/*
* OUTPUT : Map => {1=1, 2=1, 3=8, 4=2}
* 3
*/
// or in this way
System.out.println(".............");
Integer maxAppearedElement = map.entrySet()
.parallelStream()
.max(Comparator.comparing(Entry::getValue))
.map(Entry::getKey)
.get();
System.out.println(maxAppearedElement);
}
}
For my project, I used a slightly modified version of Jon's and Fathah's solution. In the case of multiple entries with the same value, it returns the last entry it finds:
public static Entry<String, Integer> getMaxEntry(Map<String, Integer> map) {
Entry<String, Integer> maxEntry = null;
Integer max = Collections.max(map.values());
for(Entry<String, Integer> entry : map.entrySet()) {
Integer value = entry.getValue();
if(null != value && max == value) {
maxEntry = entry;
}
}
return maxEntry;
}
This is going to return the keys with max value in a Map<Integer, Integer>
public Set<Integer> getMaxKeys(Map<Integer, Integer> map) {
if (map.isEmpty()) {
return Collections.emptySet();
}
return map
.entrySet()
.stream()
.collect(
groupingBy(
Map.Entry::getValue, TreeMap::new, mapping(Map.Entry::getKey, toSet())
)
)
.lastEntry()
.getValue();
}
Kotlin:
val key = map.toList().groupingBy { it }.eachCount().maxByOrNull { it.value }?.key
int max = 0;
// here m is a HashMap<String, Integer>
for(Map.Entry<String,Integer> entry : m.entrySet()){
if(entry.getValue() > max){
max = entry.getValue();
}
}
you can do like that
HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();
hm.put(1,10);
hm.put(2,45);
hm.put(3,100);
Iterator<Integer> it = hm.keySet().iterator();
Integer fk = it.next();
Integer max = hm.get(fk);
while(it.hasNext()) {
Integer k = it.next();
Integer val = hm.get(k);
if (val > max){
max = val;
fk=k;
}
}
System.out.println("Max Value "+max+" is associated with "+fk+" key");
The simplest way is:
Collections.max(hmap.values());

Categories

Resources