合并两个大小不同的列表,在特定条件下合并为流 api

Merge Two List which have different size, In one with stream api on certain conditions

假设我有两个列表我想合并成一个

合并条件: 与 id

比较
Case 1 : 
List 1 = [{id=1,name=null},{id=2,name=null},{id=3,name=c}]
List 2 = [{id=1,name=a},{id=2,name=b}]

合并后应该是[{id=1,name=a},{id=2,name=b},{id=3,name=c}]

Case 1 : 
List 1 = [{id=1,name=null}]
List 2 = [{id=1,name=a},{id=2,name=b}]

合并后应该是[{id=1,name=a},{id=2,name=b}]

我的代码:

 for (Object ObjofList1: list1) {
             List<DummyObject> do = new ArrayLIst();
            SomeObject sm = list2.stream()
                    .filter(list2object -> list2object.getId().equals(ObjofList1.getId()))
                    .findAny()
                    .orElse(ObjofList1);
                          do.add(dealerSalesTempObject);
          
        }

如果 list2 中有更多元素,它工作正常,但如果 list1 中有更多元素,那么我们将无法合并,因为迭代较少。

我的问题是我不想看哪个更短或哪个更长,但最终所有对象都应该在一个列表中..

可以使用流合并这两个列表,然后使用distinct,以去除重复元素,最后将其重新转换为list:

Stream.concat(list1.stream(), list2.stream()).distinct().collect(Collectors.toList());

注意:您需要在您的DummyObject中实现equalshashcode,生成时需要删除重复的元素Set.

您的案例的 HashCode 和 Equals(考虑评论中的信息):

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    StockProcessData that = (StockProcessData) o;

    if (id != null ? !id.equals(that.id) : that.id != null) return false;
    if (unContractedStock != null ? !unContractedStock.equals(that.unContractedStock) : that.unContractedStock != null)
        return false;
    return contractedStock != null ? contractedStock.equals(that.contractedStock) : that.contractedStock == null;
}

@Override
public int hashCode() {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (unContractedStock != null ? unContractedStock.hashCode() : 0);
    result = 31 * result + (contractedStock != null ? contractedStock.hashCode() : 0);
    return result;
}

在这样的问题上引入 Stream 只会无缘无故地使事情变得更复杂。根据您的示例,您只想创建一个包含两个列表中的元素的集合。这样的事情将是实现它的最简单方法:

Set<Object> resultSet = new HashSet<>(list1);
result.addAll(list2);
List<Object> resultList = new ArrayList<>(result); // optionally if u want a List

此解决方案假定您的 class 实现了 equals()hashcode() 方法。

您更新了您的问题并提到了将具有相同 ID 的对象合并为单个对象的用例。我能想到的方式是这样的:

List<DummyObject> list3 = new ArrayList<>(
    Stream
        .concat(list1.stream(), list2.stream())
        .collect(Collectors.toMap(
            DummyObject::getId, 
            Function.identity(), 
            (a, b) -> {
                 // here you can merge a and b
            }
         ))
         .values()
    );

旧答案

不需要Streams,一个简单的SortedSet就够了:

SortedSet<DummyObject> result = new TreeSet<>(Comparator.comparing(DummyObject::getId));
result.addAll(list1);
result.addAll(list2);

当你不想覆盖hashCode()equals()方法时,可以使用SortedSet。此外 result 按 id 排序。

如果您之后需要 List,您可以轻松地将其转换回来:

List<DummyObject> list3 = new ArrayList<>(result);

但是使用 Set 可能更具声明性,因为它清楚地表明没有重复可用。