首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并包含列表的对象列表

合并包含列表的对象列表
EN

Stack Overflow用户
提问于 2017-09-22 22:03:16
回答 4查看 1.4K关注 0票数 2

我有一个自定义Foo对象列表,每个对象包含两个猫和狗对象列表,如下所示:

代码语言:javascript
复制
class Foo {
   List<Cat> cats;
   List<Dog> dogs;
}

class Cat {
   int id;
}

class Dog {
   String name;
}

我有一个传递列表请求的方法,我想把它简化到一个包含每个请求的Foo对象中,狗和猫一起扁平。是否有一种干净紧凑的方法来做到这一点?

来源清单:

代码语言:javascript
复制
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等来自外部库,因此它们的源代码不能更改。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-09-23 00:09:27

这样就行了,

代码语言:javascript
复制
Foo foo = requests.stream().reduce(new Foo(), (f1, f2) -> {
            f1.cats.addAll(f2.cats);
            f1.dogs.addAll(f2.dogs);
            return f1;
        });

与lambda一样,引入bug也非常容易。保持简单,多写几行就行了。

票数 1
EN

Stack Overflow用户

发布于 2017-09-22 22:19:42

您可以单独收集它们,然后创建一个新的Foo对象并将您的lists分配给它。

代码语言:javascript
复制
 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());

然后

代码语言:javascript
复制
Foo result = new Foo();
result.setDogs(collectDogs);
result.setCats(collectCats);
票数 5
EN

Stack Overflow用户

发布于 2017-09-22 22:21:32

若要合并多个Foo对象,请使用Java8流实现一个合并方法:

代码语言:javascript
复制
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对象中。

代码语言:javascript
复制
List<Foo> requests = ...;
Foo merged = requests.stream().reduce(new Foo(), Foo::merge);

更新

上面的代码对于并行使用是不安全的,因为merge()方法更新了当前对象。为了并行使用,应该将Foo对象视为不可变的。

此外,还提出了一个问题,即类Foo来自外部库,不能更改,因此merge()方法需要分离。

所以,这样做吧:

代码语言:javascript
复制
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,您可以这样做:

代码语言:javascript
复制
Optional<Foo> merged = requests.stream().reduce(Test::merge);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46373808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档