Java 根据依赖于其他列表的条件对列表进行分组
当涉及到创建流的对象的属性时,流分组对我来说很清楚,但如何根据依赖于其他列表的条件对对象进行分组。下面是带有嵌套循环的代码,我想将其转换为流解决方案Java 根据依赖于其他列表的条件对列表进行分组,java,java-stream,Java,Java Stream,当涉及到创建流的对象的属性时,流分组对我来说很清楚,但如何根据依赖于其他列表的条件对对象进行分组。下面是带有嵌套循环的代码,我想将其转换为流解决方案 public class Main { public static void main(String[] args) { LocalDate n = LocalDate.from(LocalDate.now()); List<LocalDate> groupingDates = Arrays
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 +
'}';
}
}
公共类主{
公共静态void main(字符串[]args){
LocalDate n=LocalDate.from(LocalDate.now());
List groupingDates=Arrays.asList(n,n.plusDays(10),n.plusDays(20));
List itemsToBeGrouped=Arrays.asList(
//应转到标有“n”的组
新项目(n,n.plusDays(1)),
新项目(第5天、第7天),
//应转到标有“n.plusDays(10)”的组
新项目(n.plusDays(5)、n.plusDays(11)),
//应转到标有“n.plusDays(20)”的组
新项目(n.plusDays(15)、n.plusDays(20));
Map groupedItems=newlinkedhashmap();
对于(项目i:ItemsToBeGroup){
对于(LocalDate日期:groupingDates){
如果(i活动日期(i,日期)){
如果(!groupedItems.containsKey(日期)){
put(date,newarraylist());
}
groupedItems.get(date).add(i);
}
}
}
System.out.println(groupedItems);
}
静态布尔值isActiveOnDate(项目、LocalDate){
return!item.start.isAfter(日期)和&!item.end.isBefore(日期);
}
}
公共类项目{
公共本地日期开始;
公共日期结束;
公共项(LocalDate开始、LocalDate结束){
this.start=start;
this.end=end;
}
@凌驾
公共字符串toString(){
返回“项目{”+
“开始=”+开始+
“,end=“+end”+
'}';
}
}
在groupingBy
lambda中执行与在for循环中相同的操作,选择项目匹配的第一个日期,然后将其用作键:
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
));
Map groupedItems=itemsToBeGrouped.stream()
.collect(Collectors.groupingBy(i->groupingDates.stream())
.filter(d->isActiveOnDate(i,d))
.findFirst()//可选
.get()//如果没有匹配项,则将抛出
));
Map groupedItems2=itemsToBeGrouped.stream()
.flatMap(x->groupingDates.stream()
.filter(y->isActiveOnDate(x,y))
.map(y->newsimplentry(x,y)))
.collect(收集器.groupingBy(
SimpleEntry::getValue,
LinkedHashMap::新建,
Collectors.mapping(条目::getKey,Collectors.toList());
您的问题在哪里?您可以使用合适的键(这意味着传递一个函数,像您正在做的那样在这些日期上进行迭代…)我建议使用findFirst()
overfindAny()
。您所说的“数据不一致”是什么意思?有什么例子吗?@Nikolas nevermind,我在OP的代码中读到了一些甚至不存在的东西<代码>findFirst
应该是一致性的首选。所以你完全正确,我编辑过:)
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())));