Как найти самую последнюю дату по заданному значению карты в 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


ему нужно самое большое значение, а не ключ
мангуста

1

Ошибка дизайна. Не помещайте свои даты на карту в виде строк. Положите 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);

Как получить ключ в результате?
учиться

Смотрите мое дополнение. Думал, ты просто хотел ценность. Моя вина.
WJS

Я получаю сообщение об ошибке с вашим новым кодом - Map.entry ("0", "0000-00-00") - в нем говорится, что метод map.entry не определен для типа Map ..
Learn Groovy

Вы должны запустить что-то более старое, чем Java 9 (когда это было добавлено). Я предложу альтернативу и объясню это.
WJS

Да, я использую Java 8
учиться

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

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

Вы можете сделать либо:

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.