如何在Java中从给定的地图值中查找最新日期


10

我有下面的值的哈希映射,在值中我已经日期为字符串数据类型。我想比较地图中所有可用的日期,并仅提取一个具有最近日期的键值。

我想与值而不是键进行比较。

我已包含以下代码

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

相关:查找具有最高值(可能会相等)的映射键(在Stack Exchange Code Review上)。
Ole VV

Answers:


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

结果如何获取密钥?
学习groovy

见我的补充。以为您只是想要价值。Mea Culpa。
WJS

我发现了一个错误跟你的新代码-为Map.Entry(“0”,“0000-00-00”) -它说的Map.Entry方法没有定义的类型映射表..
学习常规

您必须运行的版本早于Java 9(已添加版本)。我将提供替代方法并进行解释。
WJS

是的,我正在使用Java 8
学习groovy

6

Collections.maxentrySet一起使用

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

乍一看,使用String文字来表示Date并不是一种好方法,并且使其更加脆弱且易于出错。您宁愿先使用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

如果您只需要取消上述建议的日期的String表示形式,则可以使上述解决方案更加简单明了。

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


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.