我有一组对象,我们称它们为A,B,C,D ...,有些与其他相等。如果A和C相等,那么我想用对A的引用替换对C的所有引用。这意味着(a)对象C可以被垃圾回收,释放内存,并且(b)我以后可以使用“ ==”比较对象以代替昂贵的equals()
操作。 (这些对象很大,equals()
操作很慢。)
我的本能是使用java.util.Set
。当我遇到CI时,可以很容易地看到Set
中是否有一个等于C的条目。但是,如果存在,似乎没有简单的方法来找出该条目是什么,并取代我对现有条目的引用条目。我错了吗?遍历所有条目以找到匹配的条目显然是不入门的。
当前,我使用的是Set
而不是Map
,其中的值始终与键相同。调用map.get(C)
会发现A。这可行,但令人难以置信。有没有更优雅的方法呢?
答案 0 :(得分:3)
这个问题不是简单的重复数据删除:它是规范化的一种形式。
标准方法是使用Map
而不是Set
。这是如何做的草图:
public <T> List<T> canonicalizeList(List<T> input) {
HashMap<T, T> map = new HashMap<>();
List<T> output = new ArrayList<>();
for (T element: input) {
T canonical = map.get(element);
if (canonical == null) {
element = canonical;
map.put(canonical, canonical);
}
output.add(canonical);
}
return output;
}
请注意,这是O(N)
。如果可以安全地假设input
中重复项的百分比可能很小,则可以将map
和output
的容量设置为input
的大小。
现在,您似乎在说您已经以这种方式进行了操作(最后一段),并且您正在询问是否有更好的方法。据我所知,没有一个。 (通过HashSet
API,您可以测试集合中是否包含等于element
的值,但不能让您找出O(1)
中的值。)
对于它的价值,HashSet<T>
类在内部被实现为HashMap<T, T>
。因此,您将不会直接使用HashSet
来节省时间或空间...