我有一个自定义Foo对象列表,每个对象包含两个猫和狗对象列表,如下所示:
class Foo {
List<Cat> cats;
List<Dog> dogs;
}
class Cat {
int id;
}
class Dog {
String name;
}我有一个传递列表请求的方法,我想把它简化到一个包含每个请求的Foo对象中,狗和猫一起扁平。是否有一种干净紧凑的方法来做到这一点?
来源清单:
List<Cat> catsForOne = new ArrayList<>(); // add a bunch of cats
List<Cat> catsForTwo = new ArrayList<>(); // add a bunch of cats
List<Dog> dogsForTwo = new ArrayList<>(); // add a bunch of dogs
List<Foo> requests = new ArrayList<>();
Foo one = Foo.builder().cats(catsForOne).build();
Foo two = Foo.builder().dogs(dogsForTwo).cats(catsForTwo).build();
requests.add(one);
requests.add(two);其结果应是:
具有List = catsForOne + catsForTwo和List = dogsForTwo的Foo
这是一个玩具的例子,但你可以想象,foo大约有5-6集(即.猫、狗、猪、鸭等)我想用Java 8提供一个简洁的解决方案,我可以做的一个简单的解决方案就是循环处理请求,并将所有的集合逐一添加到最终结果Foo中。
假设Foo、Cat、Dog等来自外部库,因此它们的源代码不能更改。
发布于 2017-09-23 00:09:27
这样就行了,
Foo foo = requests.stream().reduce(new Foo(), (f1, f2) -> {
f1.cats.addAll(f2.cats);
f1.dogs.addAll(f2.dogs);
return f1;
});与lambda一样,引入bug也非常容易。保持简单,多写几行就行了。
发布于 2017-09-22 22:19:42
您可以单独收集它们,然后创建一个新的Foo对象并将您的lists分配给它。
List<Dog> collectDogs = foos.stream().flatMap(foo -> foo.getCats().stream())
.collect(Collectors.toList());
List<Cat> collectCats = foos.stream().flatMap(foo -> foo.getDogs().stream())
.collect(Collectors.toList());然后
Foo result = new Foo();
result.setDogs(collectDogs);
result.setCats(collectCats);发布于 2017-09-22 22:21:32
若要合并多个Foo对象,请使用Java8流实现一个合并方法:
class Foo {
List<Cat> cats;
List<Dog> dogs;
Foo merge(Foo other) {
this.cats.addAll(other.cats);
this.dogs.addAll(other.dogs);
return this;
}
}现在,您可以使用Foo流方法轻松地将List中的所有Foo对象合并到单个Foo对象中。
List<Foo> requests = ...;
Foo merged = requests.stream().reduce(new Foo(), Foo::merge);更新
上面的代码对于并行使用是不安全的,因为merge()方法更新了当前对象。为了并行使用,应该将Foo对象视为不可变的。
此外,还提出了一个问题,即类Foo来自外部库,不能更改,因此merge()方法需要分离。
所以,这样做吧:
class Test {
public static void test() {
List<Foo> requests = ...;
Foo merged = requests.stream().reduce(new Foo(), Test::mergeFoos);
}
public static Foo mergeFoos(Foo a, Foo b) {
Foo merged = new Foo();
merged.cats = mergeLists(a.cats, b.cats);
merged.dogs = mergeLists(a.dogs, b.dogs);
merged.pigs = mergeLists(a.pigs, b.pigs);
merged.ducks = mergeLists(a.ducks, b.ducks);
return merged;
}
private static <E> List<E> mergeLists(List<E> a, List<E> b) {
List<E> merged = new ArrayList<>(a.size() + b.size());
merged.addAll(a);
merged.addAll(b);
return merged;
}
}如果您不希望在列表为空时创建一个Foo,您可以这样做:
Optional<Foo> merged = requests.stream().reduce(Test::merge);https://stackoverflow.com/questions/46373808
复制相似问题