使用Java集进行重复数据删除

时间:2018-09-11 20:12:03

标签: java collections

我有一组对象,我们称它们为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。这可行,但令人难以置信。有没有更优雅的方法呢?

1 个答案:

答案 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中重复项的百分比可能很小,则可以将mapoutput的容量设置为input的大小。


现在,您似乎在说您已经以这种方式进行了操作(最后一段),并且您正在询问是否有更好的方法。据我所知,没有一个。 (通过HashSet API,您可以测试集合中是否包含等于element的值,但不能让您找出O(1)中的值。)

对于它的价值,HashSet<T>类在内部被实现为HashMap<T, T>。因此,您将不会直接使用HashSet来节省时间或空间...