我可以流式传输两个列表之间的差异,其中字段设置为 Java 中的特定内容吗?

问题描述 投票:0回答:3

我有以下课程:

public class Person {
    private String name;
    private String gender;
}

然后我有两个人员名单

名单A:

index 0: name: "Mike", gender: "male"
index 1: name: "Jane", gender: "female"
index 2: name: "Ellen", gender: "female"
index 3: name: "Ben", gender: "male"
index 4: name: "Jimmy", gender: "male"
index 5: name: "Maria", gender: "female"

名单B:

index 0: name: "Ben", gender: "male"
index 1: name: "Maria", gender: "female"
index 2: name: "Jane", gender: "female"
index 3: name: "Brian", gender: "male"
index 4: name: "Sofia", gender: "female"
index 5: name: "John", gender: "male"
index 6: name: "Jimmy", gender: "male"

我想创建一个新列表,其中包含不在两个列表中的所有男性的姓名。

因此从示例来看,列表将如下所示:

index 0: name: "Mike", gender: "male"
index 1: name: "John", gender: "male"
index 2: name: "Brian", gender: "male"

这里棘手的事情是过滤是双向的。我希望最终列表包含列表 A 中但不在列表 B 中的男性,以及列表 B 中但不在列表 A 中的男性。我无法找到如何执行此操作,但我'我尝试使用流来完成它..

java stream java-stream
3个回答
1
投票

不是超级有效,但有效

List<Person> r =
  Stream.concat(
    a.stream().filter(e -> e.isMale() && !b.contains(e)),
    b.stream().filter(e -> e.isMale() && !a.contains(e))
  )
  .collect(Collectors.toList());

更易读的版本,可存储部分结果

List<Person> aNotB = a.stream().filter(e -> e.isMale() && !b.contains(e)).collect(Collectors.toList());
List<Person> bNotA = b.stream().filter(e -> e.isMale() && !a.contains(e)).collect(Collectors.toList());
List<Person> r = new ArrayList<>(aNotB);
r.addAll(bNotA);

0
投票
List<String> malesNotInBothLists = listA.stream()
    .filter(p -> p.getGender().equals("male"))
    .filter(p -> !listB.stream().anyMatch(b -> b.getName().equals(p.getName())))
    .map(Person::getName)
    .collect(Collectors.toList());

malesNotInBothLists.addAll(listB.stream()
    .filter(p -> p.getGender().equals("male"))
    .filter(p -> !listA.stream().anyMatch(a -> a.getName().equals(p.getName())))
    .map(Person::getName)
    .collect(Collectors.toList()));`enter code here`

0
投票
Set<String> namesA = listA.stream()
        .filter(p -> "male".equals(p.gender))
        .map(p -> p.name)
        .collect(Collectors.toUnmodifiableSet());
Set<String> namesB = listB.stream()
        .filter(p -> "male".equals(p.gender))
        .map(p -> p.name)
        .collect(Collectors.toUnmodifiableSet());

List<String> result = Stream.concat(
        namesA.stream().filter(Predicate.not(namesB::contains)),
        namesB.stream().filter(Predicate.not(namesA::contains))
).toList();

说明

这首先构建了

Set
listA
中男性名字的
listB
。事实上,这些是
Set
而不是
List
很重要,因为检查一个元素是否在
Set
中比在
List
中快得多(通常
Set
的时间为常数,但为线性时间)对于
List
)。

然后,这将创建一个组合结果

List
,其中包含
namesA
中不在
namesB
中的所有元素,反之亦然。

© www.soinside.com 2019 - 2024. All rights reserved.