从原始列表创建所有重复项的单独列表

时间:2014-08-13 15:01:00

标签: java algorithm duplicates

我有一个对象列表。每个对象都有一个布尔重复变量。在我的算法结束时,我希望所有具有多个对象(由对象上的字符串标识符标识的重复项)具有boolean duplicate = true。我这样做了,但我想知道是否有办法更有效地做到这一点,理想情况下只有一个循环。

List<String> dupIds = new ArrayList<String>();
Map<String, MyObject> objMap = new HashMap<String, MyObject>();  
for (MyObject o : objectList) {
    if (objMap.containsKey(o.getId()) {
        dupIds.add(o.getId());
    } else {
        objMap.put(o.getId(), o);
    }
}

for (MyObject o : objectList) {
    if (dupIds.contains(o.getId) {
        o.setDuplicate(true);
    }
}

希望这不是一个重复的问题,但我发现的大多数都不是这样做的,通常只是删除重复(我需要保留它们)或只标记副本(我需要标记副本加上原件)。

2 个答案:

答案 0 :(得分:1)

这不是最有效的方法,但它摆脱了第二个循环:

Map<String, MyObject> objMap = new HashMap<String, MyObject>();  
for (MyObject o : objectList) {
    if (objMap.containsKey(o.getId()) {
        objMap.get(o.getId()).setDuplicate(true);
        o.setDuplicate(true);
    } else {
        objMap.put(o.getId(), o);
    }
}

如果在地图中找到重复项,则会将当前对象和地图中的对象标记为重复。如果一个对象出现两次以上,您可能会多次在同一个对象上调用setDuplicate,因此您可能需要在设置之前检查该标志是否已设置。

更新:

这是一个不会在同一个对象上多次调用setDuplicate的解决方案:

Map<String, MyObject> objMap = new HashMap<String, MyObject>();  
for (MyObject o : objectList) {
    if (objMap.containsKey(o.getId()) {
        MyObject other = objMap.get(o.getId());
        if (other != null) {
            othet.setDuplicate(true);
            objMap.put(o.getId(), null);
        }
        o.setDuplicate(true);
    } else {
        objMap.put(o.getId(), o);
    }
}
  • 第一次遇到对象时,将其放入地图中。
  • 当你第二次遇到一个对象时,你setDuplicate到当前对象和地图中的对象,然后在地图中输入一个空值作为对象ID的值。 / LI>
  • 第3次(或更多次)遇到对象时,只有setDuplicate到当前对象。

答案 1 :(得分:1)

我可能首先使用两个哈希集找到所有重复的键,然后在每个对象上设置布尔值。

它与你的解决方案(和Eran&#39; s)具有相同的渐近时间复杂度,这是O(n),但我发现这更容易理解(但这仅仅是品味问题,当然)。

Set<String> keys = new HashSet<>();
Set<String> duplicateKeys = new HashSet<>();

for (MyObject o : objectList) {
    if (keys.contains(o.getId())
        duplicateKeys.add(o.getId());
    keys.add(o.getId());
}

for (MyObject o : objectList) {
    o.setDuplicate(duplicateKeys.contains(o.getId()));
}