我的问题有点复杂(我认为),所以我会尝试使用一个例子。希望你能理解我的问题。
设置说我有一个用户列表:
List<User> users;
其中:
public class User{
private List<Car> cars;
}
public class Car{
private String code;
private List<Feature> features;
}
public class Feature{
private String code;
}
我想要实现的是从用户列表中获取汽车列表但我也希望这个列表是不同的(没有相同代码的汽车)但我希望单个Car对象具有来自的所有功能具有相同代码的不同汽车以及我失败的地方。
现在我有
List<Car> cars = users
.stream()
.flatMap(user -> user.getCars())
.???
我知道我可以使用Predicate通过代码过滤汽车,但我很难为我要离开的那些添加功能。是否有一种干净的方式来做流?
答案 0 :(得分:2)
这一切归结为一个问题,你想如何获得Car
拥有所有联合功能。您肯定不想修改其中一个Car
的任意User
实例。因此,为了支持加入这些Feature
,您必须在加入功能列表后构建新的Car
实例。
这可以按如下方式完成:
List<Car> cars =
users.stream()
.flatMap(user -> user.getCars().stream())
.collect(Collectors.groupingBy(Car::getCode,
Collectors.mapping(Car::getFeatures, Collector.of(
ArrayList<Feature>::new, List::addAll, (a,b)->{a.addAll(b);return a;}))))
.entrySet().stream()
.map(e -> new Car(e.getKey(), e.getValue()))
.collect(Collectors.toList());
有两个步骤。第一个使用code
属性作为键执行分组操作,并将组中所有Feature
的{{1}}列表加入一个Car
。
这会产生List
。第二步将每个映射表项转换为新的Map<String,List<Feature>>
实例,假设有Car
构造函数。这些结果Car(String code, List<Feature> features)
个实例会收集到Car
。
请注意,上面的代码只是将所有List
列表连接到一个列表。如果您必须从这些列表中删除重复的Feature
,则可以使用
Feature
这首先将List<Car> cars =
users.stream()
.flatMap(user -> user.getCars().stream())
.collect(Collectors.groupingBy(Car::getCode,
Collectors.mapping(Car::getFeatures, Collector.of(
LinkedHashSet<Feature>::new, Set::addAll, (a,b)->{a.addAll(b);return a;}))))
.entrySet().stream()
.map(e -> new Car(e.getKey(), new ArrayList<>(e.getValue())))
.collect(Collectors.toList());
的{{1}}个Feature
与Car
相同的code
收集到Set
,删除重复但保留订单(对于相关的情况)和在构造结果Set
实例时,将List
转换为Car
。