如何将所有值从列表<dto1>复制到单个列表<dto2>

时间:2018-02-12 18:17:20

标签: java list collections hashmap java-stream

抱歉我的英文!

我有三个List<DTO1>

List A:

ListA{id=5, userLogin='cdp', count=14}
ListA{id=11452, userLogin='clelonginge', count=7}
ListA{id=11451, userLogin='vdupontinge', count=16}

List B:

ListB{id=5, userLogin='cdp', count=26}
ListB{id=11452, userLogin='clelonginge', count=14}
ListB{id=11451, userLogin='vdupontinge', count=6}

List C:

ListC{id=5, userLogin='cdp', count=29}
ListC{id=11452, userLogin='clelonginge', count=45}
ListC{id=11451, userLogin='vdupontinge', count=75}

我想制作第三个List<DTO2>,其中包含3个列表的count属性的值。 这就是我想要的:

List D:

ListD{id=5, userLogin='cdp', countListA=14, countListB=26, countListC=29}
ListD{id=11452, userLogin='clelonginge', countListA=7, countListB=14, countListC=45}
ListD{id=11451, userLogin='vdupontinge', countListA=16, countListB=6, countListC=75}

所以我尝试了不同的做法,比如:

ListC = ListA.stream().map(DTO1::getId).collect(Collectors.toList());

(it gave me the following error:

    Error:(475, 98) java: incompatible types: inference variable T has incompatible bounds
        equality constraints: org.ocdm.service.dto.DTO2
        lower bounds: java.lang.Long
)

或使用HashMap但我没有成功找到解决方案。

修改 ListA,ListB和ListC是相同的类型。它们的类型为:List<DTO1>

但是列表D是不同的。它的类型为:List<DTO2>.

DTO1有3个属性:id,userLogin和count。

DT02有5个属性:id,userLogin,countListA,countListB和countListC。

1 个答案:

答案 0 :(得分:-1)

如果您知道id是唯一的(没有两个id具有不同的userLogin s),那么将地图作为中间人可以提供帮助。

首先,您必须从一个列表创建地图。我们说它是listA

Map<Integer, DTO2> map = listA.stream().collect(Collectors.toMap(item->item.getId(),
                item->new DTO2(item.getId(), item.getUserLogin(), item.getCount(), 0,0)));

注意,我想你有构造函数DTO2(Integer id, String userLogin, Integer countListA, Integer countListB, Integer countListC)

其次,您使用Map.merge()添加listB中的所有项目。如果map没有键,则会创建一个新条目。如果map的key等于itemB.id则更新value。请注意,构造函数接收countB作为第4个参数。

listB.forEach(itemB -> map.merge(
            // key for our map
            itemB.getId(),
            // function to create new entry if no such key
            new DTO2(itemB.getId(), itemB.getUserLogin(), 0, itemB.getCount(),0),
            //function to update
            (existed, noMatter) -> {
                existed.setCountListB(itemB.getCount());
                return existed;
            }));

请注意merge()需要一个函数。如果item.setCountListB()没有返回任何内容,则需要在第三个参数中显式返回值。作为替代方案,您可以将其声明为DTO2 setCountListB() - 这是不寻常但可能的。

然后合并最后一个列表。请注意,我们将count作为构造函数中的第5个参数传递。

listC.forEach(itemC -> map.merge(
            itemC.getId(),
            new DTO2(itemC.getId(), itemC.getUserLogin(), 0, 0,itemC.getCount()),
            (existingItem, noMatter) -> {existingItem.setCountListC(itemC.getCount()); return existingItem;}));

最后,返回List而不是Map

return map.values().stream().collect(Collectors.toList());

请注意,代码依赖于构造函数按特定顺序接收countAcountBcountC。它可能会令人困惑,可能你想使用构建器模式,但它超出了范围。

从表现的角度来看,代码可能并不完美,但你明白了。