Comment trouver la dernière date à partir de la valeur de carte donnée en Java


10

J'ai une carte de hachage avec des valeurs ci-dessous, dans les valeurs que j'ai la date comme type de données de chaîne. Je voudrais comparer toutes les dates qui sont disponibles dans la carte et extraire une seule valeur-clé qui a une date très récente.

Je voudrais comparer avec des valeurs et non des clés.

J'ai inclus le code ci-dessous

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

}

La sortie attendue pour celui-ci est:

Valeur clé 4 2014-09-09


il a besoin de la plus grande valeur, pas de la clé
mangusta


Erreur de conception. Ne mettez pas vos dates dans votre carte sous forme de chaînes. Mettez des LocalDateobjets. Le reste du code sera probablement le même, sauf la déclaration du type de la carte.
Ole VV

Réponses:


1

Cela devrait fournir la date la plus récente (ou la plus grande) par rapport aux autres.

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

Si vous souhaitez également la clé, faites-le et renvoyez un Map.Entry. Nécessite 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());

Cela suppose que votre carte n'est pas vide. s'il est vide, il renvoie une valeur nulle. Fonctionne avec Java 8+

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

Comment obtenir la clé en conséquence?
apprenez groovy

Voir mon ajout. Je pensais que vous vouliez juste la valeur. Mea culpa.
WJS

Je reçois une erreur avec votre nouveau code - Map.entry ("0", "0000-00-00") - il dit que la méthode map.entry n'est pas définie pour le type Map ..
apprenez groovy

Vous devez exécuter quelque chose de plus ancien que Java 9 (date à laquelle il a été ajouté). Je vais proposer une alternative et l'expliquer.
WJS

Oui j'utilise Java 8
apprenez groovy

6

Utiliser Collections.max avec entrySet

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

ou

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

Le Map.Entry.comparingByValue()est astucieux (depuis Java 8).
Ole VV

4

À première vue, l'utilisation de littéraux de chaîne pour représenter la date n'est pas une bonne approche et la rend plus fragile et sujette aux erreurs. Vous préférez utiliser LocalDateen premier lieu. Cependant, en supposant que vous n'avez aucun contrôle sur ce format de données (par exemple, il provient d'un autre système tiers), nous pouvons toujours concevoir une approche qui résout le problème actuel. Voici à quoi ça ressemble.

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

Le LocalDate.parseest utilisé pour convertir la représentation sous forme de chaîne de la date en un LocalDatequi est un comparable. Cela Comparableest ensuite transmis comme clé de la Comparatorméthode de construction. Et voici la paire clé-valeur de sortie lors de l'exécution réussie:

4=2014-09-09

Si vous pouvez simplement vous passer de la représentation String de la date comme suggéré ci-dessus, vous pouvez rendre la solution ci-dessus beaucoup plus simple et succincte.

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

3

Cela devrait fonctionner

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

la sortie est Optional[4=2014-09-09]


Merci, cher .. mais je cherche la clé du résultat
apprenez groovy

1

Vous pouvez analyser la chaîne LocalDateet la trier dans l'ordre inverse

 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

Vous pouvez faire soit:

import java.util.Map.Entry;

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

ou :

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

Les deux produiront le même résultat.


Le Map.Entry.comparingByValue()est astucieux (depuis Java 8).
Ole VV
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.