如何替换流的 while 循环或 Flux 以迭代我的元素

How to replace a while loop for a stream or a Flux to iterate my elements

我有这个代码

public String calculateShippingEstimateDate(LocalDateTime initialDate, Integer totalDaysToAdd, SaveOrderSourceData saveOrderSourceData) {

        int workDays = totalDaysToAdd;
        LocalDateTime finalDate = LocalDateTime.of(initialDate.getYear(),
                initialDate.getMonth(),
                initialDate.getDayOfMonth(),
                initialDate.getHour(),
                initialDate.getMinute(),
                initialDate.getSecond());

        while (workDays > 0) {
            finalDate = finalDate.plusDays(1);

            if (!(
                    DateUtility.isWeekend(finalDate.getDayOfWeek())
                            || checkHolidays(saveOrderSourceData, finalDate)
            )) {
                workDays--;
            }
        }
        return finalDate.toString();
    }



    private boolean checkHolidays(SaveOrderSourceData saveOrderSourceData, LocalDateTime finalDate) {
        return saveOrderSourceData.getHolidays()
                .stream().anyMatch(holiday -> getHoliday(holiday).isEqual(finalDate.toLocalDate()));
    }

    private LocalDate getHoliday(Holiday holiday){
        return LocalDate.of(holiday.getYear(),holiday.getMonth(), holiday.getDay());
    }

重要的是要知道此示例的估计日期等于初始日期后五天。

我们有一个 initialDate(15/02/2022) 等于 finalDate。

我们进入 while 循环,它验证工作日(在本次迭代中为 5)是否为 0,为假,因此 finalDate 增加其值,并验证日期(16/02/2022)是周末或假期,依此类推,当 finalDate 等于 (19/02/2022) 时,它不会减少 workDays 的值。最后,当 finalDate 为 (21/02/2022) workDays 等于 0,且 finalDate 为星期一时,w​​hile 循环结束。

假期Class

import lombok.Builder;
import lombok.Data;

@Data
@Builder(toBuilder = true)
public class Holiday {
    private final String id;
    private final int year;
    private final int month;
    private final int day;
}

DateUtility Class

import java.time.DayOfWeek;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;

public class DateUtility {

    private DateUtility() {
    }

    public static boolean isWeekend(DayOfWeek dayOfWeek) {
        return SATURDAY.equals(dayOfWeek)
                || SUNDAY.equals(dayOfWeek);
    }
}

SaveOrderSourceDataclass

@Data
@Builder(toBuilder = true)
public class SaveOrderSourceData {

    private  final List<Holiday> holidays;
}

这将等同于您的 while 循环。

  • iterate()initialDate.plusDays(1) 作为种子,并根据 UnaryOperator date -> date.plusDays(1);
  • 生成新元素
  • filter() - 在流中只生活工作日(假设 DateUtilitycheckHolidays() 正确地完成工作);
  • limit() - 顾名思义,将流中的元素数量限制为给定值(注意,过滤掉周末或假期时应用 limit());
  • max() - 生成可选结果,可选结果可能为空 initialDate 并且给定范围内的所有其他日期为周末或假期,在这种情况下流将为空;
  • map() - 如果值存在则应用于可选;
  • orElse() - 提供替代值(以及在您的实现中,如果没有找到进一步的日期,它将 return initialDate)。
    public String calculateShippingEstimateDate(LocalDateTime initialDate, 
                                                Integer totalDaysToAdd, 
                                                SaveOrderSourceData saveOrderSourceData) {

        return Stream.iterate(initialDate.plusDays(1), date -> date.plusDays(1))
                .filter(date -> !(DateUtility.isWeekend(date.getDayOfWeek())
                                || checkHolidays(saveOrderSourceData, date)))
                .limit(totalDaysToAdd)
                .max(Comparator.naturalOrder())
                .map(LocalDateTime::toString)
                .orElse(initialDate.toString());
    }

我已经使用您的实用程序测试了此解决方案 类 它产生与您的命令式实施相同的结果

    public static void main(String[] args) {
        System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 5, SaveOrderSourceData.builder().holidays(List.<Holiday>of()).build()));
        System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 5, SaveOrderSourceData.builder().holidays(List.<Holiday>of()).build()) + "\n");

        System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 27, SaveOrderSourceData.builder().holidays(List.of(Holiday.builder().id("id1").year(2022).month(3).day(3).build())).build()));
        System.out.println(new LDTUtil().getShippingDateLoop(LocalDateTime.now(), 27, SaveOrderSourceData.builder().holidays(List.of(Holiday.builder().id("id1").year(2022).month(3).day(3).build())).build()));
    }

输出

2022-02-22T21:43:25
2022-02-22T21:43:25

2022-03-25T21:43:25
2022-03-25T21:43:25