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

apprendre groovy
la source
il a besoin de la plus grande valeur, pas de la clé
mangusta
1
OK, essayez stackoverflow.com/questions/109383/…
Scary Wombat
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);
WJS
la source
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()));
        }
});
bathudaide
la source
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);
Ravindra Ranwala
la source
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]

Rajkumar Natarajan
la source
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
Dead Pool
la source
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.

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