Java 8 Stream - 对集合中具有相同 id 的对象进行操作

qwe*_*423 1 java collections java-8 java-stream

我的问题有点复杂(我认为),所以我会尝试使用一个例子。希望你能理解我的问题。

设置说我有一个用户列表:

List<User> users;
Run Code Online (Sandbox Code Playgroud)

在哪里:

public class User{
    private List<Car> cars;
}

public class Car{
    private String code;
    private List<Feature> features;
}

public class Feature{
    private String code;
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是从用户列表中获取汽车列表但是我也希望这个列表是不同的(没有具有相同代码的汽车)但是我希望单个 Car 对象具有来自不同汽车的所有功能相同的代码,这就是我失败的地方。

现在我有

List<Car> cars = users
        .stream()
        .flatMap(user -> user.getCars())
        .???
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用 Predicate 通过代码过滤汽车,但我很难为我要离开的汽车添加功能。有没有一种干净的方法来处理流?

Hol*_*ger 5

这一切都归结为一个问题,您希望如何获得Car所有联合功能。您肯定不想修改sCar之一的任意实例User。因此,为了支持加入这些Features,您必须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());
Run Code Online (Sandbox Code Playgroud)

有两个步骤。第一个使用code属性作为键执行分组操作,并将组Feature中所有Cars的列表连接为一个List
这会产生一个Map<String,List<Feature>>. 第二步将每个映射条目转换为一个新Car实例,假设有一个Car(String code, List<Feature> features)构造函数。这些结果Car实例被收集到一个List.

请注意,上面的代码只是将所有Feature列表连接到一个列表。如果您必须Feature从这些列表中消除重复的s,您可以使用

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());
Run Code Online (Sandbox Code Playgroud)

这首先将Features 的Cars 与相同的s收集code到 a 中Set,消除重复但保留顺序(对于相关的情况),并在构造结果实例时将 the 转换Set为 a 。ListCar