如何在地图中找到最新的 joda DateTime?

How do I find the most recent joda DateTime in map?

我有一张从 Firebase 实时数据库更新的地图,所以我事先不知道地图大小。

在地图中,我有一个字符串作为键,一个 Joda DateTime 作为值。

我不知道如何通过地图迭代到 return 最近的日期时间。

我会尽力解释得更好:

//on returning results from Realtime Database
  Map<String, DateTime> myMap = new HashMap<>();

    if(dataSnapshot.exists){

       for(DataSnapshot data:dataSnapshot.getChildren()){

           String key = data.getKey();
           DateTime dateTime = // I get the data and convert it to Datetime; no problem here; I can do it.

           myMap.put(key, dateTime);

       }

   //outside the Loop
   //HERE IS WHAT I NEED HELP WITH

      for(DateTime date:myMap.values()){

         // 1 - check if date is after the next date in map
         // 2 - if it is, then keep it
         // 3 - if it is not, then remove
         // 4 - in the end, only one pair of key/value with the most recent date is left

      }

    }

你们能帮帮我吗? 非常感谢

编辑:抱歉,还有一件事。我在 Android 中使用了最小的 sdk,它不允许我使用 Java 8。我必须使用 Java 7 个功能。

您可以对地图值中的 DateTime 个对象使用 .isAfter() 方法来检查一个对象是否在另一个对象之后。

创建一个 String mostRecentKey 变量或类似的变量并将其设置为映射中的第一个键值。 然后遍历 myMap.keySet(),将每个日期对象值与最近的对象值 .isAfter() 进行比较。最后,您将看到最近的日期。

例如

String mostRecentKey;
for (String dateKey : myMap.keySet()){
    if (mostRecentKey == null) {
        mostRecentKey = dateKey;
    }
    // 1 - check if date is after the next date in map
    if (myMap.get(dateKey).isAfter(myMap.get(mostRecentKey))) {
        mostRecentKey = dateKey;
    }
}

那么你就有了最近那个的key,你可以选择删除除那个以外的所有条目,保存值或者任何你想要的。

要删除除您找到的条目以外的所有条目,请在此处参考此问题:

基本上,您可以这样做:

myMap.entrySet().removeIf(entry -> !entry.getKey().equals(mostRecentKey));

编辑 - 忘记了您无法修改正在迭代的集合,稍微更改了方法。

how to iterate through the map to return the most recent Datetime

Java 8+ 使用流:

// To get latest key (or entry)
String latestKey = myMap.entrySet().stream()
        .max(Entry::comparingByValue)
        .map(Entry::getKey) // skip this to get latest entry
        .orElse(null);
// To get latest value
DateTime latestValue = myMap.values().stream()
        .max(Comparator.naturalOrder())
        .orElse(null);

任何使用 for 循环的 Java 版本:

Entry<String, DateTime> latestEntry = null;
for (Entry<String, DateTime> entry : myMap.entrySet()) {
    if (latestEntry == null || entry.getValue().isAfter(latestEntry.getValue()))
        latestEntry = entry;
}
String latestKey = (latestEntry != null ? latestEntry.getKey() : null);

以上根据自己需要最新的key、value还是entry(key+value),按需调整。


in the end, only one pair of key/value with the most recent date is left

最好的办法是在找到最新条目后替换地图,或者至少替换内容。

Java 8+ 使用 Streams(替换地图):

myMap = myMap.entrySet().stream()
        .max(Comparator.comparing(Entry::getValue))
        .stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue));

任何使用for循环的Java版本(替换内容):

Entry<String, DateTime> latestEntry = null;
for (Entry<String, DateTime> entry : myMap.entrySet()) {
    if (latestEntry == null || entry.getValue().isAfter(latestEntry.getValue()))
        latestEntry = entry;
}
myMap.clear();
if (latestEntry != null)
    myMap.put(latestEntry.getKey(), latestEntry.getValue());

您也可以遍历 entrySet,保存最新的条目,然后删除所有条目,然后再添加那个条目。

    Map<String, DateTime> myMap = new HashMap<>();
    ....

    Entry<String, DateTime> latest = myMap.entrySet().iterator().next();
    for(Entry<String, DateTime> date:myMap.entrySet()){

         // 1 - use isAfter method to check whether date.getValue() is after latest.getValue()
         // 2 - if it is, save it to the latest
      }
    myMap.clear();
    myMap.put(latest.getKey(), latest.getValue());

Java7个解

I'm using a minimum sdk in Android that doesn't ler me use Java 8. I have to use Java 7 features.

    Map<String, DateTime> myMap = new HashMap<>();
    myMap.put("a", new DateTime("2020-01-31T23:34:56Z"));
    myMap.put("b", new DateTime("2020-03-01T01:23:45Z"));
    myMap.put("m", new DateTime("2020-03-01T01:23:45Z"));
    myMap.put("c", new DateTime("2020-02-14T07:14:21Z"));

    if (myMap.isEmpty()) {
        System.out.println("No data");
    } else {
        Collection<DateTime> dateTimes = myMap.values();
        DateTime latest = Collections.max(dateTimes);

        System.out.println("Latest date-time is " + latest);
    }

此片段的输出在我的时区(在 jdk.1.7.0_67 上测试):

Latest date-time is 2020-03-01T02:23:45.000+01:00

我们需要先检查地图是否为空,因为Collections.max()如果是空的会抛出异常。

如果您需要从地图中删除除该条目或持有最新日期的条目之外的所有条目:

        dateTimes.retainAll(Collections.singleton(latest));
        System.out.println(myMap);

{b=2020-03-01T02:23:45.000+01:00, m=2020-03-01T02:23:45.000+01:00}

是不是有点棘手? retainAll 方法从集合中删除所有不在作为参数传递的集合中的元素。我们传递一组只有一个元素,最新的日期时间,所以所有其他元素都被删除。从我们从 myMap.values() 获得的集合中删除元素会反映在我们从中获得集合的映射中,因此值不是最新日期的条目将被删除。所以这个调用完成了它。

旁注:考虑 ThreeTenABP

如果您还没有大量使用 Joda-Time,您可以考虑使用 java.time、现代 Java 日期和时间 API 以及 Joda-Time 的后继者,反而。它已被反向移植并在低 Android API 水平上工作。

java.time 链接