Java 如何在列表中查找重复项以合并它们

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

我有一份可能重复的清单。我通过ID识别重复项。对象有子对象,现在我想合并重复项,以便子对象仅附加到一个对象。我如何才能最好地识别重复项,可能是流

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]]]