对于创建流的对象的属性,流分组对我来说很清楚,但是如何根据条件来分组对象,而条件取决于其他列表。下面是带有嵌套循环的代码,我想将其转换为流解决方案。
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 +
'}';
}
}
答案 0 :(得分:2)
在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
));
答案 1 :(得分:1)
Map<LocalDate, List<Item>> groupedItems2 = itemsToBeGrouped.stream()
.flatMap(x -> groupingDates.stream()
.filter(y -> isActiveOnDate(x, y))
.map(y -> new SimpleEntry<>(x, y)))
.collect(Collectors.groupingBy(
SimpleEntry::getValue,
LinkedHashMap::new,
Collectors.mapping(Entry::getKey, Collectors.toList())));