我有一个对象列表(例如List和我必须在列表中找到重复。我没有UnknownSrcClass的源代码,UnknownSrcClass没有哈希码和equals实现。所以我不能把它在Set中找到重复项
我有以下两个解决方案
HashMap<String,List<UnknownSrcClass>>
,其中将使用负责相等性检查的字段构建密钥。如果键列表大小&gt;则迭代HashMap; 1然后迭代项目列表并找到重复项
请建议我哪一个更有效率的表现。对我来说,#3是更好的方法。
答案 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();
}
}