英文:
Merge Two List which have different size, In one with stream api on certain conditions
问题
假设我有两个列表,我想要将它们合并成一个
**合并条件:
按照 id 进行比较**
情况 1:
列表 1 = [{id=1,name=null},{id=2,name=null},{id=3,name=c}]
列表 2 = [{id=1,name=a},{id=2,name=b}]
合并后,应该得到 [{id=1,name=a},{id=2,name=b},{id=3,name=c}]
情况 2:
列表 1 = [{id=1,name=null}]
列表 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` 中的元素更多,由于迭代次数较少,我们将无法合并。
我的问题是,我不想知道哪个列表较短或较长,但最终所有对象都应该在一个列表中。
英文:
Suppose I have two list which i want to get merged into one
Merge Condition :
compare with 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}]
After the merge, it should be [{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}]
After the merge, it should be [{id=1,name=a},{id=2,name=b}]
My code:
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);
}
It is working fine if list2
has more elements in it, but if list1
has more element then we won't be able to merge because of less iteration.
My question is i don't want to see which one is shorter or longer but at last all objects should be in one list..
答案1
得分: 4
介绍流(Stream)到这样的问题只会使事情变得更复杂,没有真正的理由。根据你的示例,你只想要创建一个包含两个列表元素的集合(Set)。以下是实现这一目标最简单的方法:
Set<Object> resultSet = new HashSet<>(list1);
resultSet.addAll(list2);
List<Object> resultList = new ArrayList<>(resultSet); // 可选,如果你想要一个列表(List)
这个解决方案假设你的类实现了 equals()
和 hashcode()
方法。
英文:
Introducing Stream to such problem just makes things more complicated for no real reason. Based on your example you just want to create a Set containing elements from both Lists. Something like this would be the easiest way to achieve it:
Set<Object> resultSet = new HashSet<>(list1);
result.addAll(list2);
List<Object> resultList = new ArrayList<>(result); // optionally if u want a List
This solution assumes that your class implements equals()
and hashcode()
methods.
答案2
得分: 2
你可以使用流(streams)合并这两个列表,然后使用 distinct
方法来删除重复元素,最后将其重新转换为 list
:
Stream.concat(list1.stream(), list2.stream()).distinct().collect(Collectors.toList());
注意: 你需要在你的 DummyObject
中实现 equals
和 hashcode
方法,以便在生成 Set
时删除重复元素。
针对你的情况,考虑到注释中的信息,这是 equals
和 hashcode
的实现:
@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;
}
英文:
You can merge these two lists using streams, and then use distinct
, in order to remove duplicate elements, and finally reconvert it to a list
:
Stream.concat(list1.stream(), list2.stream()).distinct().collect(Collectors.toList());
NOTE: you need to implement equals
and hashcode
in your DummyObject
, it's required to remove the duplicated elements when generating the Set
.
HashCode and Equals for your case (Considering the infos in the comments):
@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;
}
答案3
得分: 2
你已更新问题,并提到将具有相同 id 的对象合并为单个对象的用例。我能想到的方法类似于这样:
List<DummyObject> list3 = new ArrayList<>(
Stream
.concat(list1.stream(), list2.stream())
.collect(Collectors.toMap(
DummyObject::getId,
Function.identity(),
(a, b) -> {
// 在这里你可以合并 a 和 b
}
))
.values()
);
旧回答
不需要使用 Stream
,一个简单的 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
可能更具有声明性,因为它明确表示没有重复项可用。
英文:
You have updated your question and mentioned the use case of merging objects with the same id into a single object. The way I can think of would be something like this:
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()
);
Old answer
No need for Stream
s, a simple SortedSet
is enough:
SortedSet<DummyObject> result = new TreeSet<>(Comparator.comparing(DummyObject::getId));
result.addAll(list1);
result.addAll(list2);
The SortedSet
can be used when you don't want to override the hashCode()
and equals()
methods. Additionally the result
is sorted by id.
If you need a List
afterwards you can convert it easily back:
List<DummyObject> list3 = new ArrayList<>(result);
But using a Set
may be more declarative, as it clearly indicates that no duplicates are available.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论