将流元素映射到 LocalDate 而不收集到列表

Map stream elements to LocalDate without collecting to list

假设我有一个表示每日数据的整数流:

Stream.of(12,19,7,13,42,69);

其中每个数字都属于从 2020 年 1 月 22 日开始的一个日期,我想要一张地图 Map<LocalDate,Integer>

所以基本上我需要这样的东西:

22.01.2020  = 12
23.01.2020  = 19
24.01.2020  = 7
25.01.2020  = 13
26.01.2020  = 42
27.01.2020  = 69

如何从给定日期(例如 2020 年 1 月 22 日)开始递增密钥 (LocalDate)?

Map<LocalDate,Integer> map = Stream.of(12,19,7,13,42,69)
              .collect(Collectors.toMap(x -> **LocalDate.of(2020,1,22)**, x -> x));

实现这个有点困难,主要是因为您同时使用 Stream<LocalDate>Stream<Integer>。一个 hack 是将开始日期存储在单元素数组中并在 Collector:

中修改它
LocalDate[] startDate = { LocalDate.of(2020, Month.JANUARY, 21) };

Map<LocalDate, Integer> map = Stream.of(12, 19, 7, 13, 42, 69)
    .collect(Collectors.toMap(x -> {
        startDate[0] = startDate[0].plusDays(1L);
        return startDate[0];
    }, Function.identity()));

System.out.println(map);

这个输出是:

{2020-01-27=69, 2020-01-26=42, 2020-01-25=13, 2020-01-24=7, 2020-01-23=19, 2020-01-22=12}

更简洁的解决方案是创建自定义 Collector,这样您就可以支持收集并行 Stream

更简洁的解决方案可能是使用 IntStream 例如:

LocalDate firstDay = LocalDate.of(2020, Month.JANUARY, 22);
List<Integer> data = List.of(12, 19, 7, 13, 42, 69);
Map<LocalDate, Integer> finalMap = IntStream.range(0, data.size())
        .mapToObj(day -> Map.entry(firstDay.plusDays(day), data.get(day)))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

或者,如果您坚持使用 Stream<Integer> 作为数据输入,使用 AtomicInteger 也不会是一个坏主意,同时限制执行顺序执行:

LocalDate firstDay = LocalDate.of(2020, Month.JANUARY, 22);
AtomicInteger dayCount = new AtomicInteger();
Map<LocalDate, Integer> finalMap = Stream.of(12, 19, 7, 13, 42, 69)
        .map(data -> Map.entry(firstDay.plusDays(dayCount.getAndIncrement()), data))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println(finalMap);