我想将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);
}
}
}
然后我想使用过滤器(例如,使用姓氏)从临时人员中删除某些人。
for (Person tmp : temp) {
for (Person one : first) {
if (one.getSurname.equals(tmp.getSurname)) {
temp.remove(tmp);
}
}
}
我想使用lambda表达式,我该怎么办?
答案 0 :(得分:2)
您可以这样做
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.get(p.getName()) != null)
.filter(p -> !nameToSurname.get(p.getName()).contains(p.getSurname()))
.collect(Collectors.toList());
首先使用第二个列表创建一个从map
到所有具有该名称的surnames
的{{1}}。然后遍历第一个列表,对于每个人,通过将名称作为键来检查地图中是否有值。如果是,则检查姓氏是否与当前人的姓氏匹配。如果两个条件都满足,则将其收集到容器中。
答案 1 :(得分:1)
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);
答案 2 :(得分:0)
Lambda并不总是最好的解决方案。
您可以使用retainAll
中的Collection<E>
方法。
fist.retainAll(second);
答案 3 :(得分:0)
两个for-loop
可能被压缩为两个documentation方法:
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());
答案 4 :(得分:0)
这是方法引用和not
的解决方案。
second.stream()
.filter(first.stream.map(Person::getName).collect(toSet())::contains)
.filter(not(first.stream.map(Person::getSurname).collect(toSet())::contains))
.collect(toList());
我没有在IDE中编写代码。可能会有一些编译器错误。