последняя дата формирует список строк, включая название месяца - PullRequest
0 голосов
/ 10 октября 2019

Привет Я ищу быстрый и компактный способ получить самую последнюю дату из ArrayList<String> дат, которые имеют следующий формат (я намереваюсь сгенерировать это из базы данных). Содержимое ArrayList будет иметь следующий формат:

ArrayList<String> datelist=new ArrayList<String>(); 
datelist.add("October 09, 2019");
datelist.add("August 20, 2018");
datelist.add("October 09, 2019");
datelist.add("August 31, 2019");

конечный результат должен быть строкой, подобной October 09, 2019, любые идеи относительно функций или логики будут оценены

РЕДАКТИРОВАТЬ: Спасибо всем за ваши предложения :). Так как мне нужно было общее решение для обработки необработанных данных (как выяснилось при проверке всех ваших предложений), и выше были примеры данных ... такие проблемы, как дата, упомянутая на других языках, как упомянуто @deHaar, всплыли иподход, предложенный @Eritrean, был наиболее подходящим для меня

Ответы [ 6 ]

2 голосов
/ 10 октября 2019

Пример получения максимальной даты из списка дат

Преобразование списка строк в список LocalDate, а остальные операции будут выполняться с помощью приведенного ниже кода.

LocalDate maxDate = dates.stream()
                            .max( Comparator.comparing( LocalDate::toEpochDay ) )
                            .get();

LocalDate minDate = dates.stream()
                            .min( Comparator.comparing( LocalDate::toEpochDay ) )
                            .get();
1 голос
/ 10 октября 2019

Не помещайте строки в свой список. Положите LocalDate объектов. Точно так же, как вы не будете хранить числа в виде строк в списке (я надеюсь).

Кроме того, я нашел код в некоторых других ответах немного многословным. С помощью LocalDate объектов в списке можно найти самую последнюю дату в одной строке.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM dd, uuuu", Locale.ENGLISH);

    List<LocalDate> dateList = new ArrayList<>(); 
    dateList.add(LocalDate.parse("October 09, 2019", dateFormatter));
    dateList.add(LocalDate.parse("August 20, 2018", dateFormatter));
    dateList.add(LocalDate.parse("October 09, 2019", dateFormatter));
    dateList.add(LocalDate.parse("August 31, 2019", dateFormatter));

    LocalDate latest = Collections.max(dateList);
    System.out.println("End result: " + latest.format(dateFormatter));

Выходные данные этого фрагмента:

Конечный результат: 09 октября 2019 г.

Поскольку названия месяцев указаны на английском языке, мы должны предоставить англоязычную локализацию, чтобы убедиться, что код работает на всех JVM независимо от настроек локали по умолчанию.

Collections.maxвыдаст NoSuchElementException, если список пуст.

Если вы не можете позволить себе изменить список, чтобы он содержал LocalDate объектов только сейчас, используя тот же форматер, что и раньше:

    String latest = Collections.max(datelist,
            Comparator.comparing(s -> LocalDate.parse(s, dateFormatter)));
    System.out.println("End result: " + latest);

Вывод такой же, как и раньше.

1 голос
/ 10 октября 2019

Как уже упоминалось в комментариях, должно работать что-то похожее на приведенное ниже:

    ArrayList<String> datelist=new ArrayList<>(); 
        datelist.add("October 09, 2019");
        datelist.add("August 20, 2018");
        datelist.add("October 09, 2019");
        datelist.add("August 31, 2019");

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.US);
        String maxDate = datelist.stream()
                .map(d -> LocalDate.parse(d, dtf))
                .max(Comparator.comparing(LocalDate::toEpochDay))
                .get().format(dtf);
        System.out.println(maxDate);
0 голосов
/ 10 октября 2019

Попробуйте использовать LocalDate с DateTimeFormatter:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
String maxDate = datelist.stream()
        .map(str -> LocalDate.parse(str, dateTimeFormatter))
        .max(LocalDate::compareTo)
        .map(dateTimeFormatter::format)
        .orElse("N/A");
0 голосов
/ 10 октября 2019

Вы можете преобразовать / разобрать дату String s в сопоставимые объекты и затем легко найти максимум (самая новая / самая последняя дата):

public static void main(String[] args) {
    // provide a list of sample data
    List<String> datelist = new ArrayList<String>();
    datelist.add("October 09, 2019");
    datelist.add("August 20, 2018");
    datelist.add("October 09, 2019");
    datelist.add("August 31, 2019");

    // create a list of LocalDates
    List<LocalDate> localDates = new ArrayList<>();

    datelist.forEach(date -> {
        // parse every String in the datelist using a matching pattern
        LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("MMMM dd, yyyy"));
        // and add each resulting LocalDate to the list of LocalDates
        localDates.add(localDate);
    });

    // find the most recent LocalDate (the maximum here)
    LocalDate mostRecentDate = localDates.stream().max(LocalDate::compareTo).get();
    // and print it in the ISO format (or the one of your choice
    System.out.println(mostRecentDate.format(DateTimeFormatter.ISO_LOCAL_DATE));
}

Стоит упомянуть: это не удалось на моем(Немецкая) система, потому что LocalDate в Германии не знает месяц октябрь , а Октябрь . Я заменил 'c' в этом месяце, и он заработал.
Это означает, что ваша система должна быть английской, чтобы этот код работал.

РЕДАКТИРОВАТЬ
Проблема с языком полностью решена в ответе @Eritrean, который использует DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.US);.

0 голосов
/ 10 октября 2019

Ваш формат "ММММ дд, гггг"

  DateTimeFormatter format = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
  Optional<LocalDate> latest = datelist.stream()
            .map(format::parse)
            .map(p -> LocalDate.of(p.get(ChronoField.YEAR), p.get(ChronoField.MONTH_OF_YEAR), p.get(ChronoField.DAY_OF_MONTH)))
            .max(LocalDate::compareTo);
  String output = latest.map(format::format).orElse("no elements");
...