我想将Java lambda表达式用于两个列表的交集,然后将lambda表达式用于从列表中删除。
示例:我有
List<Person> first = new ArrayList<Person>();
List<Person> second = new ArrayList<Person>();
假设两个列表都具有某些Person对象。我想将按名称过滤的两个列表的列表温度交集放入列表,例如:
List<Person> temp = new ArrayList<>();
for (Person one : first) {
for (Person two : second) {
if(one.getName.equals(two.getName)) {
temp.add(two);
}
}
}
然后,我想使用过滤器(例如,使用姓氏)从临时人员中删除某些Person。
for (Person tmp : temp) {
for (Person one : first) {
if (one.getSurname.equals(tmp.getSurname)) {
temp.remove(tmp);
}
}
}
我想使用lambda表达式,我该怎么办?
您可以这样做,
Map<String, Set<String>> nameToSurname = second.stream().collect(
Collectors.groupingBy(Person::getName,
Collectors.mapping(Person::getSurname, Collectors.toSet())));
List<Person> temp = first.stream().
filter(p -> nameToSurname.containsKey(p.getName()))
.filter(p -> !nameToSurname.get(p.getName()).contains(p.getSurname()))
.collect(Collectors.toList());
首先使用第二个列表从mame到具有该名称的所有map
创建一个surnames
。然后遍历第一个列表,对于每个人,通过将名称作为键来检查地图中是否有值。如果是,则检查姓氏是否与当前人的姓氏匹配。如果两个条件都满足,则将其收集到容器中。
first
和second
之间的交点:
List<Person> intersection = first.stream()
.filter(p1 -> second.stream().anyMatch(p2 -> p2.getName().equals(p1.getName())))
.collect(Collectors.toList());
基于myList
中的元素删除first
中的元素:
first.stream()
.filter(p1 -> myList.stream().anyMatch(p2 -> p1.getSurName().equals(p2.getSurName())))
.forEach(myList::remove);
Lambda并不总是最好的解决方案。
您可以使用retainAll
中的Collection<E>
方法。
fist.retainAll(second);
[两个for-loop
都可能被压缩成两个Stream::filter
方法:
Stream::filter
这里是方法参考和List<Person> temp = second.stream()
.filter(s -> first.stream().anyMatch(f -> f.getName().equals(s.getName())))
.filter(s -> !first.stream().anyMatch(f -> f.getSurame().equals(s.getSurame())))
.collect(Collectors.toList());
的解决方案。
not
我没有在IDE中编写代码。可能会有一些编译器错误。