英文:
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 Streams, 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论