Цикл for с помощью Stream API

Рейтинг: -1Ответов: 3Опубликовано: 13.08.2023

Есть метод, пытаюсь переделать цикл for через Stream API, но не выходит((( Ребята подскажите пожалуйста можно ли тут что-то придумать и сделать через Stream, много чего перепробовал но пока не нашёл решение, интересно что среда разработки, как вариант, подсказывает что лучше использовать цикл)))

public LocalDate getDate() {
        LocalDate date = LocalDate.now().plusDays(1);
        List<Order> sortOrder = orderDao.sortedByDate();

        for (Order order : sortOrder) {
            LocalDate endDate = order.getEndDate();
            if (endDate.isEqual(date)){
                date = date.plusDays(1);
            }
        }
        return date;
    }

Ответы

▲ 1Принят

Немного модифицирую предыдущий ответ:

        final LocalDate date = LocalDate.now().plusDays(1);
        List<Order> sortOrder = orderDao.sortedByDate();

        long numberOfDaysToAdd = sortOrder.stream()
                .map(Order::getEndDate)
                .filter(new Predicate<>() {

                    int сount;
                    boolean result;

                    @Override
                    public boolean test(LocalDate endDate) {
                        if(result = endDate.equals(date.plusDays(сount))) сount++;
                        return result;
                    }
                })
                .count();

        return date.plusDays(numberOfDaysToAdd);

Заменяем лямбду в методе filter на анонимный класс, который будет хранить количество успешных сравнений. Соответственно сравнивать будем с учётом этого количества (увеличивая исходный объект data на сохранённое раньше количество успешных сравнений).

И да, с параллельными стримами лучше не использовать)

▲ 0

Если хочется стримом:

    public LocalDate getDate2() {
    final LocalDate date = LocalDate.now().plusDays(1);
    List<Order> sortOrder = orderDao.sortedByDate();
    
    long numberOfDaysToAdd = sortOrder.stream()
            .map(Order::getEndDate)
            .filter(endDate -> endDate.isEqual(date))
            .count();
    return date.plusDays(numberOfDaysToAdd);
  }

Обратите внимание, что plusDays всегда возвращает новый объект LocalDate, а у Вас он в цикле. Правильнее будет сперва посчитать, сколько дней нужно прибавить.

▲ 0

Стримы здесь не совсем подходят, так как здесь имеется изменчивое состояние date и соответственно придётся использовать некий контейнер, чтобы date выглядело условно финальной (effectively final) для стрима.

При этом модифицировать значение date нужно будет на этапе фильтра, так что "решение" на стриме может выглядеть так:

public LocalDate getDate() {
    AtomicReference<LocalDate> ld = new AtomicReference<>(LocalDate.now().plusDays(1));
        
    return orderDao.sortedByDate()
        .stream()               // Stream<Order>
        .map(Order::getEndDate) // Stream<LocalDate>
        .filter(d -> {
            boolean r = d.isEqual(ld.get());
            if (r) {
                // простое присваивание ld = d.plusDays(1); запрещено
                ld.set(d.plusDays(1)); 
            }
            return r;
        })
        .max(Comparator.naturalOrder()) // Optional<LocalDate>
        .map(d -> d.plusDays(1))
        .orElse(ld.get());
}

Очевидно, что в данном случае решение с использованием Stream API не выглядит лучшим образом, и к тому же стрим должен быть по умолчанию упорядоченным.