重复数据删除HashMap值

时间:2012-01-31 22:10:56

标签: java arraylist hashmap deduplication

我想知道是否有人知道删除LinkedHashMap中重复值的好方法?我有LinkedHashMap成对的StringList<String>。我想删除ArrayList的重复项。这是为了改善一些下游处理。

我唯一能想到的就是在迭代HashMap然后遍历ArrayList时保留已处理值的日志,并检查我之前是否遇到过值。随着列表的增长,这种方法似乎会降低性能。有没有办法预处理HashMap以删除ArrayList值中的重复项?

说明......如果我有 String1&gt; List1(a,b,c) String2&gt; List2(c,d,e) 我想删除“c”,因此HashMap中的列表中没有重复项。

6 个答案:

答案 0 :(得分:1)

我相信创建第二个HashMap,可以按值排序(按字母顺序,按数字排序),然后对排序列表进行单次扫描,以检查当前节点是否等效于下一个节点,如果它是,删除下一​​个,并保持增量相同,因此它将保持在该排序列表的相同索引。

或者,当您添加值时,您可以检查它是否已包含此值。

答案 1 :(得分:1)

鉴于你的澄清,你想要这样的东西:

class KeyValue {
    public String key;
    public Object value;

    KeyValue(String key, Object value) {
        this.key = key;
        this.value = value;
    }

    public boolean equals(Object o) {
        // boilerplate omitted, only use the value field for comparison
    }

    public int hashCode() {
        return value.hashCode();
    }
}

public void deduplicate() {
    Map<String, List<Object>> items = new HashMap<String, List<Object>>();
    Set<KeyValue> kvs = new HashSet<KeyValue>();

    for (Map.Entry<String, List<Object>> entry : items.entrySet()) {
        String key = entry.getKey();
        List<Object> values = entry.getValue();
        for (Object value : values) {
            kvs.add(new KeyValue(key, value));
        }
        values.clear();
    }

    for (KeyValue kv : kvs) {
        items.get(kv.key).add(kv.value);
    }
}

使用set将删除重复值,KeyValue允许我们保留原始哈希键。根据需要添加getter和setter或泛型。这也将修改原始地图及其中的列表。我也认为这个的表现应该是O(n)。

答案 2 :(得分:0)

我假设你需要独特的元素(包含在你的列表中)而不是唯一的列表。

如果Map的键和其关联List中的元素之间不需要关联,只需将所有元素分别添加到Set中即可。

如果将所有列表添加到集合中,它将包含唯一的列表对象,而不是列表的唯一元素,因此您必须单独添加元素。

(当然,您可以使用addAll来简化此操作)

答案 3 :(得分:0)

使用Guava

Map<Value, Key> uniques = new LinkedHashMap<Value, Key>();
for (Map.Entry<Key, List<Value>> entry : mapWithDups.entrySet()) {
  for (Value v : entry.getValue()) {
    uniques.put(v, entry.getKey());
  }
}
ListMultimap<K, V> uniqueLists = Multimaps.invertFrom(Multimaps.forMap(uniques), 
  ArrayListMultimap.create());
Map<K, List<V>> uniqueListsMap = (Map) uniqueLists.asMap(); // only if necessary

应该保留值的顺序,并保持它们的唯一性。如果你可以使用ListMultimap<K, V>来获得你的结果 - 你可能会这样做 - 那就去吧,否则你可能只是将uniqueLists.asMap()投射到Map<K, List<V>>(有些滥用泛型,但保证类型安全)。

答案 4 :(得分:0)

所以,澄清......你基本上有K,[V1 ... Vn]并且你想要所有V的唯一值?

public void add( HashMap<String, List> map, HashMap<Objet, String> listObjects, String key, List values)
{
    List uniqueValues= new List();
    for( int i  = 0; i < values.size(); i++ ) 
    {
        if( !listObjects.containsKey( values.get(i) ) )
        {
            listObjects.put( values.get(i), key );
            uniqueValues.add( values.get(i) );
        }
    }
    map.put( key, uniqueValues);
} 

基本上,我们有另一个HashMap存储列表值,我们在向地图添加列表时删除非唯一的HashMap。这也为您提供了解值的列表所带来的额外好处。

答案 5 :(得分:0)

正如其他人所说,您可以在添加时检查该值,但是,如果您必须在事后执行此操作:

static public void removeDups(Map<String, List<String>> in) {
        ArrayList<String> allValues = new ArrayList<String>();
        for (List<String> inValue : in.values())
           allValues.addAll(inValue);
        HashSet<String> uniqueSet = new HashSet<String>(allValues);

        for (String unique : uniqueSet)
            allValues.remove(unique);

        // anything left over was a duplicate
        HashSet<String> nonUniqueSet = new HashSet<String>(allValues);

        for (List<String> inValue : in.values())
           inValue.removeAll(nonUniqueSet);

     }


     public static void main(String[] args) {
        HashMap<String, List<String>> map = new HashMap<String, List<String>>();
        map.put("1", new ArrayList(Arrays.asList("a", "b", "c", "a")));
        map.put("2", new ArrayList(Arrays.asList("d", "e", "f")));
        map.put("3", new ArrayList(Arrays.asList("a", "e")));

        System.out.println("Before");
        System.out.println(map);

        removeDups(map);
        System.out.println("After");
        System.out.println(map);

     }

生成

的输出
Before
{3=[a, e], 2=[d, e, f], 1=[a, b, c, a]}
After
{3=[], 2=[d, f], 1=[b, c]}