Как мне найти самую последнюю версию joda DateTime на карте? - PullRequest
1 голос
/ 14 февраля 2020

У меня есть карта, которая обновляется из базы данных Firebase Realtime, поэтому я не знаю заранее размер карты.

На карте у меня есть строка в качестве ключа и Joda DateTime в качестве значение.

Я не знаю, как выполнить итерацию по карте, чтобы получить самый последний Datetime.

Я попытаюсь объяснить лучше:

//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

      }

    }

Может ребята, пожалуйста, помогите мне? Большое вам спасибо

РЕДАКТИРОВАТЬ: Извините, еще одна вещь. Я использую минимальный sdk в Android, который не лишает меня возможности использовать Java 8. Я должен использовать Java 7 функций.

Ответы [ 4 ]

2 голосов
/ 14 февраля 2020

как выполнить итерацию по карте для возврата самого последнего значения 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);

Any Java версия с использованием for l oop:

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

В приведенной выше настройке при необходимости отрегулируйте в зависимости от того, нужен ли вам последний ключ, значение или запись (ключ + значение).


в конце концов, остается только одна пара ключ / значение с самой последней датой

Лучший способ - заменить карту или хотя бы заменить содержимое после поиск последней записи.

Java 8+ с использованием потоков (замена карты):

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

любая версия Java с использованием for l oop (замена содержимого):

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());
1 голос
/ 14 февраля 2020

Java 7 решение

Я использую минимальный sdk в Android, который не дает мне пользы Java 8. Я должен использовать Java 7 функций.

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

Последняя дата-время: 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 ссылки

1 голос
/ 14 февраля 2020

Вы можете использовать метод .isAfter() для объектов DateTime в значениях карты, чтобы проверить, один за другим.

Создайте переменную 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;
    }
}

Затем у вас есть ключ самой последней, и вы можете удалить все записи, кроме этой. , сохраните значение или что хотите.

Чтобы удалить все, кроме записи, которую вы нашли, обратитесь к этому вопросу здесь: Удалите все записи из HashMap, где значение НЕ то, что я ищу

По сути, вы можете сделать что-то вроде этого:

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

Изменить - Забыл, что вы не можете изменить коллекцию, через которую вы перебираете, немного изменил метод.

0 голосов
/ 14 февраля 2020

Вы также можете перебрать 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());
...