Java在列表中查找副本

时间:2016-09-22 20:58:35

标签: java collections

我有一个对象列表(例如List和我必须在列表中找到重复。我没有UnknownSrcClass的源代码,UnknownSrcClass没有哈希码和equals实现。所以我不能把它在Set中找到重复项

我有以下两个解决方案

  1. 构建一个HashMap<String,List<UnknownSrcClass>>,其中将使用负责相等性检查的字段构建密钥。
  2. 如果键列表大小&gt;则迭代HashMap; 1然后迭代项目列表并找到重复项

    1. 将项目放入带有Comprator的TressSet中,并检查add方法的返回值。
    2. 请建议我哪一个更有效率的表现。对我来说,#3是更好的方法。

2 个答案:

答案 0 :(得分:1)

我认为#1是好的,我认为#1的成本是O(n),但#3将是&gt; O(n)只要比较将通过整个列表调用每个条目。 这是我的第一选择:

public class Main {

static class Model {
public final Long id;
public final String field1;
public final boolean fieldn;

public Model(Long id, String field1, boolean fieldn) {
    super();
    this.id = id;
    this.field1 = field1;
    this.fieldn = fieldn;
}

}

public static void main(String[] args) throws InterruptedException {

List<Model> list = Arrays.asList(new Model(1L, "sample 1", true), new Model(1L, "sample 1", true));
Map<String, List<Model>> doublications = new HashMap<>();
list.forEach(m -> checkDoublication(doublications, m));
doublications.forEach(Main::print);
// and this would print => key: "1sample 1true", doublications: 1

}

private static void print(String key, List<Model> list) {
System.out.println(String.format("key: \"%s\", doublications: %d", key, list.size()));
}

private static String key(Model model) {
return model.id + model.field1 + model.fieldn;
}

private static void checkDoublication(Map<String, List<Model>> map, Model model) {
String key = key(model);
if (!map.containsKey(key))
    map.put(key, new LinkedList<>());
else
    map.get(key)
       .add(model);

}

答案 1 :(得分:1)

第一种方法可能不比第二种方法更有效。让我们假设相等性检查基于您连接的2个字符串。获得相同的字符串有不同的可能性。

在最坏的情况下,您会得到一个HashMap,其中包含一个键,但该值中包含n个不同的元素。成对比较它们会导致O(n²)的运行时间。这比使用O(n * log(n))实现的TreeSet运行时间更糟糕。

如果您使用类似于第一种方法的内容,则创建某些内容不会导致将不同的值映射到同一个键,例如使用Arrays.asList

组合这些值
HashSet<List<Object>> set = new HashSet<>();
for (Iterator<UnknownSrcClass> iterator = list.iterator(); iterator.hasNext();) {
    UnknownSrcClass element = iterator.next();
    List<Object> lst = (element == null ? null : Arrays.asList(element.getProperty1(), element.getProperty2(), ...));
    if (!set.add(lst)) {
        // handle duplicate, e.g.
        iterator.remove();
    }
}