Java 如何在列表中查找重复项以合并它们
我有一份可能重复的清单。我通过ID识别重复项。对象有子对象,现在我想合并重复项,以便子对象仅附加到一个对象。我如何才能最好地识别重复项,可能是流Java 如何在列表中查找重复项以合并它们,java,performance,java-stream,Java,Performance,Java Stream,我有一份可能重复的清单。我通过ID识别重复项。对象有子对象,现在我想合并重复项,以便子对象仅附加到一个对象。我如何才能最好地识别重复项,可能是流 public class Foo { private String id; private Collection<String> childs; } private Collection<Foo> mergeDuplicates(Collection<Foo> fooList) { /*this
public class Foo {
private String id;
private Collection<String> childs;
}
private Collection<Foo> mergeDuplicates(Collection<Foo> fooList) {
/*this method should call the mergeChilds on found Duplicates,
and return the processed Collection of Foos*/
}
private Foo mergeChilds(Foo foo1, Foo foo2) {
...
}
公共类Foo{
私有字符串id;
私人收藏儿童;
}
私有集合合并重复项(集合傻瓜列表){
/*此方法应在找到重复项时调用mergeChilds,
并返回已处理的Foos集合*/
}
私人Foo mergeChilds(Foo Foo 1,Foo Foo 2){
...
}
映射并重新布线孩子:
List<Obj> list = ...;
Map<Long, Obj> objectsById = new HashMap<>();
list.forEach(obj -> {
objectsById.merge(obj.getId(), obj,
(oldv, v) -> {
if (oldv != null) {
v.getChildren().forEach(ch -> ch.setParent(oldv));
return oldv;
}
return v;
});
});
list = objectsById.values();
List=。。。;
Map objectsById=new HashMap();
列表。forEach(对象->{
objectsById.merge(obj.getId(),obj,
(老五,老五)->{
如果(oldv!=null){
v、 getChildren().forEach(ch->ch.setParent(oldv));
返回oldv;
}
返回v;
});
});
list=objectsById.values();
如果只有一个getParent,则没有getChildren。或者子对象也是父对象,则需要进行第二次漫游以从子对象中删除过时的对象(不显示在地图中)。您可以根据
id将它们收集到地图中,并使用合并功能将子对象合并到。然后将它们映射回最终对象,如下所示:
private Collection<Foo> mergeDuplicates(Collection<Foo> fooCollection) {
return fooCollection.stream()
.collect(Collectors.toMap(Foo::getId, Foo::getChildren, this::mergeChildren))
.entrySet().stream()
.map(e -> new Foo(e.getKey(), e.getValue()))
.collect(Collectors.toCollection(ArrayList::new)); // collect accordingly
}
注意:只有在识别基于id
的重复项时,才会执行merge函数((a,b)->{…}
)。
这将使用流查找重复项,然后将子项附加到现有对象
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class HelloWorld {
public static void main(String[] args) {
Pojo p1 = new Pojo("a", new ArrayList<String>(Arrays.asList("c1", "c2")));
Pojo p2 = new Pojo("a", new ArrayList<String>(Arrays.asList("c3", "c4")));
Pojo p3 = new Pojo("b", new ArrayList<String>(Arrays.asList("c5", "c6")));
List<Pojo> pojos = new ArrayList<Pojo>();
pojos.add(p1);
pojos.add(p2);
pojos.add(p3);
Set<Pojo> uniquePojos = new HashSet<>();
pojos.stream().filter(p -> {
boolean notExists = uniquePojos.add(p);
if (!notExists) {
for (Pojo up : uniquePojos) {
if (up.equals(p)) {
up.children.addAll(p.children);
}
}
}
return notExists;
}).collect(Collectors.toList());
System.out.println(uniquePojos);
}
}
class Pojo {
Pojo(String id, List<String> children) {
this.id = id;
this.children = children;
}
String id;
List<String> children;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pojo other = (Pojo) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Pojo [id=" + id + ", children=" + children.toString() + "]";
}
}
你能提供一个可重复的例子吗?是的,使用流是可能的,然后将数据收集到地图中并添加一些代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class HelloWorld {
public static void main(String[] args) {
Pojo p1 = new Pojo("a", new ArrayList<String>(Arrays.asList("c1", "c2")));
Pojo p2 = new Pojo("a", new ArrayList<String>(Arrays.asList("c3", "c4")));
Pojo p3 = new Pojo("b", new ArrayList<String>(Arrays.asList("c5", "c6")));
List<Pojo> pojos = new ArrayList<Pojo>();
pojos.add(p1);
pojos.add(p2);
pojos.add(p3);
Set<Pojo> uniquePojos = new HashSet<>();
pojos.stream().filter(p -> {
boolean notExists = uniquePojos.add(p);
if (!notExists) {
for (Pojo up : uniquePojos) {
if (up.equals(p)) {
up.children.addAll(p.children);
}
}
}
return notExists;
}).collect(Collectors.toList());
System.out.println(uniquePojos);
}
}
class Pojo {
Pojo(String id, List<String> children) {
this.id = id;
this.children = children;
}
String id;
List<String> children;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pojo other = (Pojo) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Pojo [id=" + id + ", children=" + children.toString() + "]";
}
}
[Pojo [id=a, children=[c1, c2, c3, c4]], Pojo [id=b, children=[c5, c6]]]