Javaで指定されたマップ値から最新の日付を見つける方法


10

文字列データ型として日付を付けた値で、以下の値のハッシュマップがあります。マップで使用可能なすべての日付を比較し、非常に最近の日付を持つKey-Valueを1つだけ抽出します。

キーではなく値と比較したいのですが。

以下のコードを含めました

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

}

これの予想される出力は次のとおりです。

キー4値2014-09-09


彼はキーではなく最大の値を必要とする
mangusta


設計エラー。日付を文字列としてマップに入れないでください。LocalDateオブジェクトを入れます。コードの残りの部分はおそらく同じで、マップのタイプの宣言を保存します。
Ole VV

回答:


1

これは、他の日付と比較して、最新の(別名:最大)日付を提供するはずです。

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

キーも必要な場合は、これを実行してMap.Entryを返します。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());

これは、マップが空でないことを前提としています。空の場合は、nullを返します。Java 8以降で動作

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

結果としてキーを取得する方法は?
2019年

私の追加を参照してください。あなただけの価値が欲しかったと思った。ミー・カルパ。
WJS 2019年

新しいコードでエラーが発生します-Map.entry( "0"、 "0000-00-00")-メソッドmap.entryはMap ..タイプに対して未定義です
groovy

Java 9より古いものを実行している必要があります(それが追加されたときです)。私は代替案を提供し、それを説明します。
WJS 2019年

はい、私はJava 8を使用しています
グルーヴィーな学習

6

entrySetでCollections.maxを使用する

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

または

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

これMap.Entry.comparingByValue()は気の利いたものです(Java 8以降)。
Ole VV

4

一見すると、文字列リテラルを使用して日付を表すのは良い方法ではなく、壊れやすく、エラーが発生しやすくなります。LocalDateそもそも使用したい。ただし、そのデータ形式を制御できない(たとえば、それが別のサードパーティシステムからのものである)ことを前提として、当面の問題を解決するアプローチを考案することができます。これがその様子です。

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

LocalDate.parse日付の文字列表現を変換するために使用されるLocalDate匹敵します。Comparable次に、それがComparator構築メソッドのキーとして渡されます。実行が成功したときの出力キーと値のペアを次に示します。

4=2014-09-09

上記のように単に日付の文字列表現を省くことができる場合は、上記のソリューションをより単純で簡潔にすることができます。

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

3

これはうまくいくはずです

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

出力は Optional[4=2014-09-09]


おかげで、親愛なる..しかし、私は結果の鍵を探しています
学ぶ

1

文字列を解析LocalDateして逆順に並べ替えることができます

 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

次のいずれかを実行できます。

import java.util.Map.Entry;

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

または:

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

どちらも同じ結果になります。


Map.Entry.comparingByValue()は気の利いたものです(Java 8以降)。
Ole VV
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.