首页 > 解决方案 > 按条件对列表进行分组,具体取决于其他列表

问题描述

当涉及到创建流的对象的属性时,流分组对我来说很清楚,但是如何按依赖于其他列表的条件对对象进行分组。下面是带有嵌套循环的代码,我想将其转换为流解决方案。

public class Main {

    public static void main(String[] args) {

        LocalDate n = LocalDate.from(LocalDate.now());

        List<LocalDate> groupingDates = Arrays.asList(n, n.plusDays(10), n.plusDays(20));
        List<Item> itemsToBeGrouped = Arrays.asList(
                //should go to group labeled by "n"
                new Item(n, n.plusDays(1)),
                new Item(n.minusDays(5), n.plusDays(7)),

                //should go to group labeled by "n.plusDays(10)"
                new Item(n.plusDays(5), n.plusDays(11)),

                //should go to group labeled by "n.plusDays(20)"
                new Item(n.plusDays(15), n.plusDays(20)));

        Map<LocalDate, List<Item>> groupedItems = new LinkedHashMap<>();
        for(Item i : itemsToBeGrouped) {
            for (LocalDate date : groupingDates) {
                if(isActiveOnDate(i, date)) {
                    if (!groupedItems.containsKey(date)) {
                        groupedItems.put(date, new ArrayList<>());
                    }
                    groupedItems.get(date).add(i);
                }
            }
        }

        System.out.println(groupedItems);
    }

    static boolean isActiveOnDate(Item item, LocalDate date) {
        return !item.start.isAfter(date) && !item.end.isBefore(date);
    }
}

public class Item{
    public LocalDate start;
    public LocalDate end;

    public Item(LocalDate start, LocalDate end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public String toString() {
        return "Item{" +
                "start=" + start +
                ", end=" + end +
                '}';
    }
}

标签: javajava-stream

解决方案


groupingBy在lambda 中执行相同的操作,就像在 中一样for-loop,选择项目匹配的第一个日期,然后将其用作键:

Map<LocalDate, List<Item>> groupedItems = itemsToBeGrouped.stream()
    .collect(Collectors.groupingBy(i -> groupingDates.stream()
        .filter(d -> isActiveOnDate(i, d))
        .findFirst() // Optional<Date>
        .get() // will throw if nothing matches
    ));

推荐阅读