我有两个狗列表 - dogsList1,dogsList2
我想创建一个具有唯一名称字段的所有狗的列表
(意思是,如果我遇到第二只同名的狗,我不会将它添加到结果列表中)
这是我在java中可以做的最好的,但是它收集了唯一的名称,而不是Dogs:
(狗包含除名称之外的其他字段)
// collect all dogs names from first list
List<String> dogNames1 = dogsList1.stream()
.map(x -> x.getName()).collect(Collectors.toList());
dogList2.stream()
.filter(x->!dogNames1.contains(x.getName()))
.forEach( x->
dogsList1.add(x);
);
可以改进吗?还有其他更好的解决方案或优化的方法吗?
答案 0 :(得分:6)
您可以使用合并多个流并删除重复项。
对于给定名字的第一只狗,你可以做
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class A {
public static void main(String[] args) {
List<Dog> dogList1 = Arrays.asList(new Dog("a", 1), new Dog("b", 2), new Dog("f", 3));
List<Dog> dogList2 = Arrays.asList(new Dog("b", 4), new Dog("c", 5), new Dog("f", 6));
List<Dog> dogList3 = Arrays.asList(new Dog("b", 7), new Dog("d", 8), new Dog("e", 9));
List<Dog> dogs = new ArrayList<>(
Stream.of(dogList1, dogList2, dogList3)
.flatMap(List::stream)
.collect(Collectors.toMap(Dog::getName,
d -> d,
(Dog x, Dog y) -> x == null ? y : x))
.values());
dogs.forEach(System.out::println);
}
}
class Dog {
String name;
int id;
public Dog(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
打印
Dog{name='a', id=1}
Dog{name='b', id=2}
Dog{name='c', id=5}
Dog{name='d', id=8}
Dog{name='e', id=9}
Dog{name='f', id=3}
在每种情况下,您都可以看到保留名称的第一个实例。
对于唯一名称
Set<String> names = Stream.of(dogList1, dogList2, dogList3)
.flatMap(List::stream)
.map(Dog::getName)
.collect(Collectors.toSet());
答案 1 :(得分:2)
这可能是一个选项
List<String> dogNames = Stream.concat(dogsList1.stream(),dogsList2.stream())
.map(x -> x.getName())
.distinct()
.collect(Collectors.toList());