【问题标题】:How can I copy all values from multiples List<DTO1> to a single List<DTO2>如何将所有值从多个 List<DTO1> 复制到单个 List<DTO2>
【发布时间】:2018-02-12 18:17:20
【问题描述】:

对不起我的英语!

我有三个List&lt;DTO1&gt;

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&lt;DTO2&gt;,其中包含 3 个列表的计数属性值。 这就是我想要的:

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&lt;DTO1&gt;

但列表 D 不同。它的类型是:List&lt;DTO2&gt;.

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

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

【问题讨论】:

  • ListA、ListB、ListC是不同的Java类型吗?
  • ListA、ListB 和 ListC 是同一类型。它们的类型为:List。但 LIst D 不同。它的类型为:List。 DTO1 有 3 个属性:id、userLogin 和 count。 DT02有5个属性:id、userLogin、countListA、countListB和countListC。
  • 我想在这里按照惯例这样做是有意义的,而不是使用流、地图和收集器
  • 您的意思是遍历所有列表吗?实际上,我简化了我的示例以便您理解它,但是我的表格有很多行和更多列。所以我认为这会减慢我的申请速度。
  • 你知道流的工作原理吗? ListC = ListA.stream().map(DTO1::getId).collect(Collectors.toList()); 告诉我你没有。也许先从那里开始?

标签: java list collections hashmap java-stream


【解决方案1】:

如果您知道 id 是唯一的(没有两个 ids 具有不同的 userLogins),那么将 map 作为中间件可能会有所帮助。

首先,您必须从一个列表创建地图。假设它是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 没有键,那么它会创建一个新条目。如果地图的键等于 itemB.id,那么它会更新值。请注意,构造函数接收 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。这可能会令人困惑,您可能想使用构建器模式,但它超出了范围。


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

【讨论】:

  • 好的,谢谢 ADS。我要试试你刚刚告诉我的!祝你一切顺利!
  • @sinaardehali 不客气。如果它解决了您的问题,请不要忘记接受答案
猜你喜欢
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多