【问题标题】:Merge Two List which have different size, In one with stream api on certain conditions [duplicate]合并两个具有不同大小的列表,在某些条件下与流 api 合并 [重复]
【发布时间】:2020-09-21 08:58:35
【问题描述】:

假设我有两个想要合并为一个的列表

合并条件: 与 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 有更多元素,那么我们将无法合并,因为迭代较少。

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

【问题讨论】:

  • 列表 1 是否合并到列表 2 中是否相关,或者是否可以反过来,即您可以将 2 列表 2 中较长的列表合并到较短的列表 1 中吗?您希望合并发生在原地,即对一个列表进行更改,还是想要列表的“合并”副本?
  • 我的问题是我不想看到哪个更短或更长,但最后所有对象都应该在一个列表中..
  • 请注意,您的代码甚至无法编译,即 do 是保留关键字,而 dealerSalesTempObject 未定义 - 请发布 minimal reproducible example
  • 这能回答你的问题吗? How do I join two lists in Java?
  • 另请参阅此相关问题:stackoverflow.com/questions/16520046/…

标签: java steam


【解决方案1】:

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

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

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

【讨论】:

  • @Lino 正确,正如您评论的那样,将其添加到我的答案中。
【解决方案2】:

您已经更新了您的问题,并提到了将具有相同 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 可能更具声明性,因为它清楚地表明没有可用的重复项。

【讨论】:

  • 我们在这里比较一个对象..但是有两个列表...我不确定..如何与列表进行比较。
  • @kole 我不太明白你的意思?你是什​​么意思:比较一个对象但有两个列表,这些列表在哪里?比较哪个对象?
  • @kole 无论何时添加元素,Set 都会使用给定的比较器来确定顺序并强制执行唯一性。
  • @Lino List1 List2 ::: 一次比较来自 list_1 或 list_2 的一个对象并将其保存在 List3 中。但我们不知道哪个对象中有更多元素。我们正在对随机列表进行迭代...最后列表 1 和列表 2 将在条件下合并
  • @kole 构造函数接受一个Comparator&lt;DummyObject&gt; 用于找出DummyObject唯一性。我们首先使用result.addAll(list1) 添加list1 的所有对象,然后另一个调用result.addAll(list2) 添加list2 的所有对象但是,将检查具有相同ID 的对象尚未存在。这意味着生成的 result 包含所有唯一对象。如果还是不明白,那我建议你看看SetSortedSetTreeSet的javadoc,或者一般ListSet的区别
【解决方案3】:

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

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

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

HashCode 和 Equals 适合您的情况(考虑 cmets 中的信息):

@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;
}

【讨论】:

  • 没有和id比较
  • 你说得对,我会编辑答案。
  • @kole 如果你在 DummyObject 类中添加 hashcode 和 equals 实现,它会起作用,你可以看到编辑,我也编辑了流。
  • @Lino 我忘记添加第二次流调用,我已经编辑了答案,对不起
  • @kole 啊,我明白了,我认为您应该在问题中指定此要求。事情会有所不同。
猜你喜欢
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-18
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多