Come trovare la data più recente dal valore della mappa indicato in Java


10

Sto avendo la mappa hash con i valori seguenti, in valori che ho datato come tipo di dati stringa. Vorrei confrontare tutte le date disponibili nella mappa ed estrarre solo un valore-chiave che ha una data molto recente.

Vorrei confrontare con valori e non chiavi.

Ho incluso il codice qui sotto

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

}

L'output previsto per questo è:

Valore chiave 4 2014-09-09


ha bisogno del valore più grande, non chiave
mangusta


Errore di progettazione. Non inserire le date nella mappa come stringhe. Metti gli LocalDateoggetti. Il resto del codice sarà probabilmente lo stesso, salvo la dichiarazione del tipo di mappa.
Ole VV,

Risposte:


1

Ciò dovrebbe fornire la data più recente (ovvero la più grande) rispetto alle altre.

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

Se vuoi anche la chiave, fallo e restituisci un Map.Entry. Richiede 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());

Questo presume che la tua mappa non sia vuota. se è vuoto, restituisce un valore nullo. Funziona con Java 8+

        Entry<String, String> ent = map.entrySet().stream().reduce(
            (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                  : a).orElseGet(() -> null);

Come ottenere la chiave come risultato?
impara l'ottimo

Vedi la mia aggiunta. Pensavo volessi solo il valore. Colpa mia.
WJS,

Ricevo un errore con il tuo nuovo codice - Map.entry ("0", "0000-00-00") - dice che il metodo map.entry non è definito per il tipo Map ..
impara groovy

Devi eseguire qualcosa di più vecchio di Java 9 (ovvero quando è stato aggiunto). Offrirò un'alternativa e la spiegherò.
WJS,

Sì, sto usando Java 8
impara l'ottimo

6

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

Il Map.Entry.comparingByValue()è nifty (dal Java 8).
Ole VV,

4

A prima vista, usare i letterali String per rappresentare Date non è un buon approccio e lo rende più fragile e soggetto a errori. Preferiresti usare LocalDatein primo luogo. Tuttavia, supponendo che tu non abbia alcun controllo su quel formato di dati (ad esempio, diciamo, provenga da un altro sistema di terze parti), possiamo ancora escogitare un approccio che risolva il problema a portata di mano. Ecco come appare.

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

Il LocalDate.parseè usato per convertire la rappresentazione in forma di stringa della data in una LocalDateche è comparabile. Questo Comparableviene quindi passato come chiave per ilComparator metodo di costruzione. Ed ecco la coppia chiave-valore di output in caso di esecuzione corretta:

4=2014-09-09

Se puoi semplicemente rinunciare alla rappresentazione String della data come suggerito sopra, puoi rendere la soluzione sopra molto più semplice e concisa.

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

3

Questo dovrebbe funzionare

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

l'uscita è Optional[4=2014-09-09]


Grazie, caro .. ma sto cercando la chiave nel risultato
impara l'ottimo

1

È possibile analizzare la stringa LocalDatee ordinarla in ordine 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

1

Puoi fare:

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

Entrambi produrranno lo stesso risultato.


Il Map.Entry.comparingByValue()è nifty (dal Java 8).
Ole VV,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.