Java 8 Stream如何使用自定义逻辑合并2个非等长列表以选择重复项

时间:2018-11-19 03:39:32

标签: java java-8 java-stream

我有2个地图对象列表。

 "list1": [
    {
      "partyId": "1",
      "accountId": "1",
      "sourceSystem": "1",
    },
    {
      "partyId": "2",
      "accountId": "2",
      "sourceSystem": "2",
    }]

这是列表2。

 "list2": [
    {
      "partyId": "3",
      "accountId": "3",
      "sourceSystem": "3",
    },
    {
      "partyId": "1",
      "accountId": "2",
      "sourceSystem": "2",
    }]

现在,我需要合并list1和list2以获得此输出。

 "merged": [
    {
      "partyId": "1",
      "accountId": "1",
      "sourceSystem": "1",
    },
    {
      "partyId": "2",
      "accountId": "2",
      "sourceSystem": "2",
    },
    {
      "partyId": "3",
      "accountId": "3",
      "sourceSystem": "3",
    }]

,因此您可以看到它合并了list1和list2的1,2和3。另外,由于list2具有一个partyId = 1(也在list1中),但是详细信息(帐户ID和sourceSystem)不同,因此选择了list1中的partyId = 1。

如何使用Java 8 Stream做到这一点?或唯一的方法是将它们转换为Java对象并进行循环。

3 个答案:

答案 0 :(得分:4)

您可以一口气做到这一点,

from PIL import Image
import numpy as np

img = Image.open('test.bmp') # input image 256 x 256
img = img.convert('YCbCr')
arr_img = np.asarray(img) # (256, 256, 3)
arr_img = arr_img[:, :, 0] # (256, 256)
pi = Image.fromarray(arr_img)
pi.show()

# Save image
pi.save('out.bmp')

这是一个两步计算,其中您首先将每个partyId值的地图List<Map<String, String>> resultMap = Stream.concat(mapListOne.stream(), mapListTwo.stream()) .collect(Collectors.groupingBy(m -> m.get("partyId"), Collectors.toList())) .entrySet().stream() .map(e -> e.getValue().get(0)) .collect(Collectors.toList()); 计算为地图,然后在每个List上获取第一个元素以计算最终结果。

答案 1 :(得分:1)

一种方法可能是遍历第一个列表并使用partyId作为keyParty作为value作为Map收集:

Map<String, CustomObject> customObjectMap = customObjectList1.stream()
        .collect(Collectors.toMap(CustomObject::getPartyId, customObject -> customObject, (a, b) -> b));

然后遍历第二个列表并过滤我们现有的partyIds

customObjectList2.stream()
        .filter(customObject -> !customObjectMap.containsKey(customObject.getPartyId()))
        .forEach(customObject -> customObjectMap.put(customObject.getPartyId(), customObject));

从地图中检索values作为最终输出

List<CustomObject> merged = new ArrayList<>(customObjectMap.values());

如果修改现有集合不会对您的代码造成任何损害,那么您可以尝试从list1获取Set上的partyId

Set<String> partyIds = customObjectList1.stream().map(CustomObject::getPartyId).collect(Collectors.toSet());  // set assuming a list wouldn't have duplicate partyId

然后根据现有键从另一个列表中删除对象

customObjectList2.removeIf(p -> partyIds.contains(p.getPartyId()));

最后将All添加到一个对象列表中

customObjectList1.addAll(customObjectList2); // customObjectList1 is now your 'merged'

答案 2 :(得分:0)

如果逻辑仅仅是第一个列表中的所有项目加上第二个列表中与第一个列表中的项目不匹配的所有项目,那么:

List<Map<String,String>> result = Stream.concat(list1.stream(),
    list2.stream().filter(m2 -> list1.stream()
        .noneMatch(m1 -> m1.get("partyId").equals(m2.get("partyId"))))
    .collect(Collectors.toList());