Localizando chave associada ao valor máximo em um mapa Java


137

Qual é a maneira mais fácil de obter a chave associada ao valor máximo em um mapa?

Acredito que Collections.max (someMap) retornará a chave max, quando você desejar a chave que corresponder ao valor máximo.

Respostas:


136

Basicamente, você precisa iterar sobre o conjunto de entradas do mapa, lembrando o "máximo atualmente conhecido" e a chave associada a ele. (Ou apenas a entrada que contém os dois, é claro.)

Por exemplo:

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;
    }
}

40
+1: você pode ter mais de uma chave com o mesmo valor máximo. Esse loop fornecerá o primeiro que encontrar.
Peter Lawrey

21
Alterar> 0 para> = 0 fornecerá o último encontrado
Aaron J Lang

1
O uso de fluxos do Java 8 ajudaria mais a simplificar isso? Por exemplo: map.forEach ((k, v) -> ...
zkarthik

3
@zkarthik: Usar maxcom um comparador personalizado provavelmente seria mais simples.
Jon Skeet

112

Para completar, aqui está uma maneira de fazê-lo

countMap.entrySet().stream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();

ou

Collections.max(countMap.entrySet(), (entry1, entry2) -> entry1.getValue() - entry2.getValue()).getKey();

ou

Collections.max(countMap.entrySet(), Comparator.comparingInt(Map.Entry::getValue)).getKey();

3
(entry1, entry2) -> entry1.getValue() - entry2.getValue()é mais compacto para o comparador.
JustABit 16/05

5
O que fazer se eu quiser todas as chaves que correspondem ao valor máximo?
Mouna

4
Compacto, mas difícil de entender.
Lluis Martinez

1
Você também pode usar o método de comparação fornecido pela classe IntegercountMap.entrySet().stream().max((entry1, entry2) -> Integer.compare(entry1.getValue(), entry2.getValue())).get().getKey();
Rui Filipe Pedro

3
Ou você pode usar em Map.Entry.comparingByValue()vez disso
Alexey Grigorev

54

Este código imprimirá todas as chaves com valor máximo

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()) {  // Itrate through hashmap
            if (entry.getValue()==maxValueInMap) {
                System.out.println(entry.getKey());     // Print the key with max value
            }
        }

    }
}

47

Um liner simples usando Java-8

Key key = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();


3
Solução mais elegante e minimalizada. Obrigado
Daniel Hári 4/17

@ Samir, verifique sua versão do Java. Sleiman Jneid tenha mencionado explicitamente que ele vai trabalhar com Java 8
Vaibs

@ Vaibs eu estava usando Java 8. Não importa mais, a resposta de Hilikus funcionou para mim.
Samir

Funciona para mim assim: String max_key = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
Timur Nurlygayanov 11/01/19

8

Veja como fazê-lo diretamente (sem um loop extra explícito), definindo o apropriado 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();

6

Uma resposta que retorna um Opcional, pois o mapa pode não ter valor máximo se estiver vazio: map.entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey);


4

Java 8 maneira de obter todas as chaves com valor máximo.

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);

Além disso, você pode paralelizar usando, em parallelStream()vez destream()


4

Eu tenho dois métodos, usando este método para obter a chave com o valor máximo:

 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;
}

Como exemplo, obtendo a entrada com o valor máximo usando o método:

  Map.Entry<String, Integer> maxEntry =  getMaxEntry(map);

Usando o Java 8 , podemos obter um objeto que contém o valor máximo:

Object maxEntry = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();      

System.out.println("maxEntry = " + maxEntry);

A versão do java 8 é simples, mas eficaz! Bom trabalho
Catbuilts

3

1. Usando 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. Usando Collections.max () com uma expressão Lambda

    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. Usando Stream com referência de método

    public <K, V extends Comparable<V>> V maxUsingStreamAndMethodReference(Map<K, V> map) {
        Optional<Entry<K, V>> maxEntry = map.entrySet()
            .stream()
            .max(Comparator.comparing(Map.Entry::getValue));
        return maxEntry.get()
            .getKey();
    }

4. Usando 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. Usando iteração simples

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();
}


2

Simples de entender. No código Abaixo, maxKey é a chave que está mantendo o valor máximo.

int maxKey = 0;
int maxValue = 0;
for(int i : birds.keySet())
{
    if(birds.get(i) > maxValue)
    {
        maxKey = i;
        maxValue = birds.get(i);
    }
}

1

Esta solução está 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);

1

Elemento Majoritário / elemento max no mapa:

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);

     } 
}

1

determinado mapa

HashMap abc = novo HashMap <> ();

obtenha todas as entradas do mapa com um máximo de valores.

você pode usar qualquer um dos métodos abaixo no filtro para obter as respectivas entradas do mapa para conjuntos de valores mínimos ou máximos

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()))

se apenas quiser obter as chaves para o mapa de filtro

abc.entrySet()
       .stream()
       .filter(entry -> entry.getValue() == Collections.max(abc.values()))
       .map(Map.Entry::getKey);

se você deseja obter os valores para o mapa filtrado

abc.entrySet()
      .stream()
      .filter(entry -> entry.getValue() == Collections.max(abc.values()))
      .map(Map.Entry::getvalue)

se você deseja obter todas essas chaves em uma lista:

abc.entrySet()
  .stream()
  .filter(entry -> entry.getValue() == Collections.max(abc.values()))
  .map(Map.Entry::getKey)
  .collect(Collectors.toList())

se você deseja obter todos esses valores em uma lista:

abc.entrySet()
  .stream()
  .filter(entry -> entry.getValue() == Collections.max(abc.values()))
  .map(Map.Entry::getvalue)
  .collect(Collectors.toList())

0

Para o meu projeto, usei uma versão ligeiramente modificada da solução de Jon e Fathah. No caso de várias entradas com o mesmo valor, ele retorna a última entrada que encontra:

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;
}

0
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");

2
As respostas somente de código geralmente são desaprovadas neste fórum. Edite sua resposta para incluir uma explicação do seu código. Como ele resolve o problema do OP?
mypetlion

-2

você pode fazer assim

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");
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.