Java 重复数据消除哈希映射值

Java 重复数据消除哈希映射值,java,arraylist,hashmap,deduplication,Java,Arraylist,Hashmap,Deduplication,我想知道是否有人知道在LinkedHashMap中删除重复值的好方法?我有一个LinkedHashMap,其中有一对字符串和列表。我想删除ArrayList中的重复项。这是为了改善一些下游加工 我能想到的唯一一件事是在迭代HashMap时保存处理后的值的日志,然后通过ArrayList检查以前是否遇到过值。这种方法似乎会随着列表的增长而降低性能。是否有方法预处理HashMap以从ArrayList值中删除重复项 来说明…如果我有 String1>List1(a、b、c) String2>List

我想知道是否有人知道在
LinkedHashMap
中删除重复值的好方法?我有一个
LinkedHashMap
,其中有一对
字符串
列表
。我想删除
ArrayList
中的重复项。这是为了改善一些下游加工

我能想到的唯一一件事是在迭代
HashMap
时保存处理后的值的日志,然后通过
ArrayList
检查以前是否遇到过值。这种方法似乎会随着列表的增长而降低性能。是否有方法预处理
HashMap
以从
ArrayList
值中删除重复项

来说明…如果我有 String1>List1(a、b、c) String2>List2(c、d、e)
我想删除“c”,这样HashMap中的列表中就不会有重复项了。

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


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

我假设您需要唯一的元素(包含在列表中),而不是唯一的列表

如果地图的键与其关联列表中的元素之间不需要关联,只需将所有元素单独添加到一个集合中即可

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

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

使用:

Map uniques=newlinkedhashmap();
对于(Map.Entry:mapWithDups.entrySet()){
对于(值v:entry.getValue()){
uniques.put(v,entry.getKey());
}
}
ListMultimap uniqueLists=Multimaps.invertFrom(Multimaps.forMap(uniques),
ArrayListMultimap.create());
Map uniqueListsMap=(Map)uniqueLists.asMap();//只有在必要的时候

这应该保持值的顺序,并保持它们的唯一性。如果您可以对结果使用
ListMultimap
,您可能可以使用它,否则您可能只需将
uniquelist.asMap()
强制转换为
Map
(有一些泛型滥用,但有保证的类型安全)。

因此,为了澄清。。。你基本上有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);
} 
public void add(HashMap映射、HashMap列表对象、字符串键、列表值)
{
List uniqueValues=新列表();
对于(int i=0;i

本质上,我们有另一个HashMap来存储列表值,并且在向映射添加列表时删除非唯一值。这还为您提供了了解值出现在哪个列表中的额外好处。

根据您的说明,您需要以下内容:

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);
    }
}
class键值{
公共字符串密钥;
公共客体价值;
KeyValue(字符串键、对象值){
this.key=key;
这个值=值;
}
公共布尔等于(对象o){
//省略样板,仅使用值字段进行比较
}
公共int hashCode(){
返回值。hashCode();
}
}
公共无效重复数据消除(){
Map items=newhashmap();
Set kvs=new HashSet();
for(Map.Entry:items.entrySet()){
String key=entry.getKey();
列表值=entry.getValue();
用于(对象值:值){
添加(新键值(键,值));
}
value.clear();
}
用于(关键值kv:kvs){
项目。获取(千伏键)。添加(千伏值);
}
}

使用集合将删除重复的值,
KeyValue
允许我们在执行此操作时保留原始哈希键。根据需要添加getter和setter或泛型。这也将修改原始地图和其中的列表。我还认为这方面的性能应该是O(n)。

正如其他人所指出的,您可以在添加时检查值,但是,如果您必须在添加后进行检查:

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);

     }

你有
Map
,你不想允许重复
Foo
?据我所知,他想禁止重复
List
…但很难说出他的确切意思?我想确保LinkedHashMap中的数组列表中没有重复项。为了清晰起见,我将对问题进行编辑。是否要同时删除每个ArrayList或所有ArrayList的重复数据?只是为了澄清:您希望映射中所有列表的值都是唯一的?因此,如果您有一个map
foo=>[1,2,2,3],bar=>[2,3,3,4,5]
,那么重复数据消除的结果应该是
foo=>[1,2,3],bar=>[4,5]
?既然OP已经澄清了他想要什么,这并不是他想要的。但他想要的是疯狂的。:-)
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]}