Як знайти останню дату із заданого значення карти у 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


йому потрібна найбільша цінність, а не ключова
мангуста


Помилка дизайну. Не вкладайте дати на карту як рядки. Поставте LocalDateпредмети. Решта коду, ймовірно, буде однаковою, за винятком декларації типу карти.
Оле ВВ

Відповіді:


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

Це передбачає, що ваша карта не порожня. якщо він порожній, то він повертає нуль. Працює з Java 8+

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

Як отримати ключ в результаті?
дізнайся groovy

Дивіться моє доповнення. Думав, що ти просто хотів цінності. Меа Кульпа.
WJS

Я отримую помилку з вашим новим кодом - Map.entry ("0", "0000-00-00") - він говорить Метод map.entry не визначено для типу Map ..
дізнайтеся groovy

Потрібно запустити щось старіше Java 9 (це було додано). Я запропоную альтернативу та поясню її.
WJS

Так, я використовую Java 8
дізнайся groovy

6

Використовуйте Collections.max з entrySet

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).
Оле ВВ

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


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).
Оле ВВ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.