Cómo encontrar la última fecha del valor del mapa dado en Java

10

Tengo un mapa hash con los valores a continuación, en valores que he fechado como tipo de datos de cadena. Me gustaría comparar todas las fechas disponibles en el mapa y extraer solo un valor-clave que tenga una fecha muy reciente.

Me gustaría comparar con valores, no con claves.

He incluido el código a continuación

import java.util.HashMap;
import java.util.Map;

public class Test {

  public static void main(String[] args) {

      Map<String, String> map = new HashMap<>();
      map.put("1", "1999-01-01");
      map.put("2", "2013-10-11");
      map.put("3", "2011-02-20");
      map.put("4", "2014-09-09");

      map.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));
    }

}

El resultado esperado para este es:

Valor clave 4 09/09/2014

aprender maravilloso
fuente
necesita el mayor valor, no la clave
mangusta
1
OK, intente stackoverflow.com/questions/109383/…
Scary Wombat
Error de diseño No ponga sus fechas en su mapa como cadenas. Poner LocalDateobjetos. El resto del código probablemente será el mismo, salvo la declaración del tipo de mapa.
Ole VV
Relacionado: Encontrar las claves del mapa con los valores más altos (puede ocurrir igualdad) (en Revisión de código de intercambio de pila).
Ole VV

Respuestas:

1

Esto debería proporcionar la fecha más reciente (también conocida como la más grande) en comparación con las demás.

      String max = map.values().stream().reduce("0000-00-00",
            (a, b) -> b.compareTo(a) >= 0 ? b
                  : a);

Si también desea la clave, hágalo y devuelva un Map.Entry. Requiere Java 9+

         Entry<String, String> ent =
            map.entrySet().stream().reduce(Map.entry("0", "0000-00-00"),
                  (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                        : a);

         System.out.println(ent.getKey() + " -> " ent.getValue());

Esto supone que su mapa no está vacío. Si está vacío, devuelve un valor nulo. Funciona con Java 8+

        Entry<String, String> ent = map.entrySet().stream().reduce(
            (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                  : a).orElseGet(() -> null);
WJS
fuente
¿Cómo obtener la clave como resultado?
aprender maravilloso
Mira mi adición. Pensé que solo querías el valor. Mea culpa.
WJS
Recibo un error con su nuevo código - Map.entry ("0", "0000-00-00") - dice que el método map.entry no está definido para el tipo Map ..
aprenda groovy el
Debe estar ejecutando algo anterior a Java 9 (que es cuando se agregó). Ofreceré una alternativa y la explicaré.
WJS
Sí, estoy usando Java 8
aprende maravilloso
6

Use Collections.max con entrySet

Entry<String, String> max = Collections.max(map.entrySet(), Map.Entry.comparingByValue());

o

Entry<String, String> max = Collections.max(map.entrySet(),
    new Comparator<Entry<String, String>>() {
        @Override
        public int compare(Entry<String, String> e1, Entry<String, String> e2) {
            return LocalDate.parse(e1.getValue()).compareTo(LocalDate.parse(e2.getValue()));
        }
});
batudaida
fuente
El Map.Entry.comparingByValue()es ingenioso (desde Java 8).
Ole VV
4

A primera vista, usar literales de cadena para representar Date no es un buen enfoque y lo hace más frágil y propenso a errores. Preferiría usar LocalDateen primer lugar. Sin embargo, con el supuesto de que no tiene ningún control sobre ese formato de datos (por ejemplo, proviene de otro sistema de terceros), aún podemos idear un enfoque que resuelva el problema en cuestión. Así es como se ve.

Entry<String, String> maxEntry = map.entrySet().stream()
    .max(Comparator.comparing(e -> LocalDate.parse(e.getValue())))
    .orElseThrow(IllegalArgumentException::new);

El LocalDate.parsese utiliza para convertir la representación de cadena de la fecha en una LocalDateque sea comparable. Eso Comparableluego se pasa como una clave para el Comparatormétodo de construcción. Y aquí está el par clave-valor de salida tras la ejecución exitosa:

4=2014-09-09

Si simplemente puede prescindir de la representación de fecha de String como se sugirió anteriormente, puede hacer que la solución anterior sea mucho más simple y sucinta.

Entry<String, LocalDate> maxEntry = map.entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .orElseThrow(IllegalArgumentException::new);
Ravindra Ranwala
fuente
3

Esto debería funcionar

    Optional<Map.Entry<String, String>> result = map.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue));
    System.out.println(result);

la salida es Optional[4=2014-09-09]

Rajkumar Natarajan
fuente
Gracias, cariño ... pero estoy buscando la clave en el resultado
aprender maravilloso
1

Puede analizar la cadena LocalDatey ordenarla en orden inverso

 Entry<String, String> res = map.entrySet()
                                .stream()
                                .sorted(Comparator.comparing((Entry<String, String> entry)->LocalDate.parse(entry.getValue())).reversed())
                                .findFirst()
                                .orElse(null);  // if not present return null or empty Entry
Consorcio inactivo
fuente
1

Puedes hacer cualquiera:

import java.util.Map.Entry;

Entry<String, String> maxEntry = map.entrySet()
                                    .stream()
                                    .max(Entry.comparingByValue());
                                    .orElseThrow(NoSuchElementException::new);   

o:

Entry<String, String> max = Collections.max(map.entrySet(), Entry.comparingByValue());

Ambos producirán el mismo resultado.

ETO
fuente
El Map.Entry.comparingByValue()es ingenioso (desde Java 8).
Ole VV