Encontrar clave asociada con el valor máximo en un mapa de Java

137

¿Cuál es la forma más fácil de obtener la clave asociada con el valor máximo en un mapa?

Creo que Collections.max (someMap) devolverá la clave max, cuando desee la clave que corresponde al valor máximo.

Ben B.
fuente

Respuestas:

136

Básicamente, necesitaría iterar sobre el conjunto de entradas del mapa, recordando tanto el "máximo actualmente conocido" como la clave asociada a él. (O solo la entrada que contiene ambos, por supuesto).

Por ejemplo:

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;
    }
}
Jon Skeet
fuente
40
+1: puede tener más de una clave con el mismo valor máximo. Este bucle le dará el primero que encuentre.
Peter Lawrey
21
Cambiar> 0 a> = 0 le dará el último que encuentre
Aaron J Lang
1
¿El uso de las secuencias Java 8 ayudaría a simplificar esto más? ej .: map.forEach ((k, v) -> ...
zkarthik
3
@zkarthik: Usar maxcon un comparador personalizado probablemente sería más simple.
Jon Skeet
112

Para completar, aquí hay un forma de hacerlo

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

o

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

o

Collections.max(countMap.entrySet(), Comparator.comparingInt(Map.Entry::getValue)).getKey();
Hilikus
fuente
3
(entry1, entry2) -> entry1.getValue() - entry2.getValue()Es más compacto para el comparador.
JustABit
55
¿Qué hacer si quiero que todas las claves coincidan con el valor máximo?
Mouna
44
Compacto pero difícil de entender.
Lluis Martinez
1
También puede usar el método de comparación proporcionado por la clase IntegercountMap.entrySet().stream().max((entry1, entry2) -> Integer.compare(entry1.getValue(), entry2.getValue())).get().getKey();
Rui Filipe Pedro el
3
O puede usar Map.Entry.comparingByValue()en su lugar
Alexey Grigorev
55

Este código imprimirá todas las teclas con el 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
            }
        }

    }
}
Fathah Rehman P
fuente
47

Un trazador de líneas simple usando Java-8

Key key = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
Sleiman Jneidi
fuente
3
La solución más elegante y minimalista. Gracias
Daniel Hári
@ Samir, compruebe su versión de Java. Sleiman Jneid ha mencionado explícitamente que funcionará con Java 8
Vaibs
@Vaibs Estaba usando Java 8. Ya no importa, la respuesta de Hilikus funcionó para mí.
Samir
A mí me funciona así: String max_key = Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey();
Timur Nurlygayanov
8

Aquí se explica cómo hacerlo directamente (sin un ciclo adicional explícito) definiendo lo apropiado 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();
Amir
fuente
6

Una respuesta que devuelve un Opcional ya que el mapa puede no tener un valor máximo si está vacío: map.entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey);

Dave L.
fuente
4

Java 8 forma de obtener todas las claves con 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);

También puedes paralelizarlo usando en parallelStream()lugar destream()

Mariusz Szurgot
fuente
4

Tengo dos métodos, usando este método para obtener la clave con el 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 ejemplo, obtenga la entrada con el valor máximo utilizando el método:

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

Usando Java 8 podemos obtener un objeto que contiene el valor máximo:

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

System.out.println("maxEntry = " + maxEntry);
Jorgesys
fuente
¡La versión de Java 8 es simple pero efectiva! Buen trabajo
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 () con una expresión 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. Uso de Stream con referencia 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 iteración simple

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();
}
Manas Ranjan Mahapatra
fuente
Asumió Baldung.com baeldung.com/java-find-map-max
Sir Montes
2

Simple de entender En el siguiente código, maxKey es la clave que contiene el 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);
    }
}
umeshfadadu
fuente
1

¿Esta solución está bien?

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);
Danilo
fuente
1

Elemento mayoritario / elemento máximo en el 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);

     } 
}
Soudipta Dutta
fuente
1

mapa dado

HashMap abc = nuevo HashMap <> ();

obtener todas las entradas del mapa con un máximo de valores.

Puede usar cualquiera de los métodos a continuación en el filtro para obtener las entradas del mapa respectivas para conjuntos de valores mínimos o 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()))

si solo quieres obtener las claves para el mapa de filtro

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

si desea obtener los valores para el mapa filtrado

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

si desea obtener todas esas claves en una lista:

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

si desea obtener todos esos valores en una lista:

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

Para mi proyecto, utilicé una versión ligeramente modificada de la solución de Jon y Fathah. En el caso de múltiples entradas con el mismo valor, devuelve la última entrada que encuentra:

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;
}
plata
fuente
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");
Abdullah Uzundere
fuente
2
Las respuestas de solo código generalmente están mal vistas en este foro. Edite su respuesta para incluir una explicación de su código. ¿Cómo resuelve el problema de OP?
mypetlion
-2

puedes hacer así

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");
Parnab Sanyal
fuente