Jak znaleźć najnowszą datę z podanej wartości mapy w Javie

10

Mam mapę skrótu z niższymi wartościami, w wartościach mam datę jako ciąg danych typu. Chciałbym porównać wszystkie daty dostępne na mapie i wyodrębnić tylko jedną kluczową wartość, która ma najnowszą datę.

Chciałbym porównać z wartościami, a nie kluczami.

Podałem kod poniżej

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

}

Oczekiwany wynik dla tego wynosi:

Klucz 4 Wartość 2014-09-09

uczyć się groovy
źródło
potrzebuje największej wartości, a nie klucza
mangusta,
1
OK, spróbuj stackoverflow.com/questions/109383/...
Scary Wombat
Błąd projektu. Nie umieszczaj swoich dat na mapie jako ciągów. Umieść LocalDateprzedmioty. Reszta kodu będzie prawdopodobnie taka sama, z wyjątkiem deklaracji typu mapy.
Ole VV,
Powiązane: Znalezienie kluczy mapy o najwyższych wartościach (może wystąpić równość) (podczas przeglądu kodu wymiany stosu).
Ole VV,

Odpowiedzi:

1

Powinno to zapewnić najnowszą (czyli największą) datę w porównaniu z innymi.

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

Jeśli chcesz również klucz, zrób to i zwróć Map.Entry. Wymaga 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());

Zakłada to, że twoja mapa nie jest pusta. jeśli jest pusty, wówczas zwraca null. Działa z Javą 8+

        Entry<String, String> ent = map.entrySet().stream().reduce(
            (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                  : a).orElseGet(() -> null);
WJS
źródło
Jak zdobyć klucz?
ucz się groovy
Zobacz mój dodatek. Myślałem, że po prostu chcesz wartość. Mea culpa.
WJS,
Pojawia się błąd z twoim nowym kodem - Map.entry („0”, „0000-00-00”) - mówi Metodę map.entry jest niezdefiniowany dla typu Map ..
dowiedz się groovy
Musisz uruchomić coś starszego niż Java 9 (czyli kiedy to zostało dodane). Dam alternatywę i wyjaśnię ją.
WJS,
Tak, używam Java 8
naucz się wspaniałego
6

Użyj Collections.max z entrySet

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

lub

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()));
        }
});
batudaide
źródło
Map.Entry.comparingByValue()Jest ładne (od Javy 8).
Ole VV,
4

Na pierwszy rzut oka użycie literałów łańcuchowych do przedstawienia daty nie jest dobrym podejściem i sprawia, że ​​jest bardziej delikatne i podatne na błędy. Wolisz używać LocalDateprzede wszystkim. Jednak przy założeniu, że nie masz żadnej kontroli nad tym formatem danych (na przykład, że pochodzi on z innego systemu strony trzeciej), nadal możemy opracować podejście, które rozwiązuje dany problem. Oto jak to wygląda.

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

LocalDate.parseSłuży do konwersji znaków reprezentujący datę w formie LocalDate, która jest porównywalna. Jest Comparableto następnie przekazywane jako klucz do Comparatormetody budowy. A oto para klucz-wartość wyjściowa po pomyślnym wykonaniu:

4=2014-09-09

Jeśli możesz po prostu zrezygnować z reprezentacji ciągu według daty, jak zasugerowano powyżej, możesz uczynić powyższe rozwiązanie o wiele prostszym i zwięzłym.

Entry<String, LocalDate> maxEntry = map.entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .orElseThrow(IllegalArgumentException::new);
Ravindra Ranwala
źródło
3

To powinno działać

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

wyjście jest Optional[4=2014-09-09]

Rajkumar Natarajan
źródło
Dzięki, kochanie ... ale szukam klucza do rezultatu
naucz się wspaniałego
1

Możesz parsować ciąg LocalDatei sortować go w odwrotnej kolejności

 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
Deadpool
źródło
1

Możesz zrobić:

import java.util.Map.Entry;

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

lub:

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

Oba przyniosą ten sam wynik.

ETO
źródło
Map.Entry.comparingByValue()Jest ładne (od Javy 8).
Ole VV,