如何从哈希映射中删除重复的密钥

时间:2019-02-01 22:14:57

标签: java hashmap duplicates

我有一个清单清单。列表中有一个列表。 [[-1, 0, 1], [-1, 2, -1], [0, 1, -1]],这个列表说的结果名称。结果列表包含重复的元素的列表。 [-1,0,1][0,1,-1]相同。我要列出不包含重复项的列表。所以列表结果成为[[-1,0,1],[-1,2,-1]][[-1,2,-1],[0,1,-1]]

我读到的Hashmap不能存储重复键,但允许重复的值。因此,要删除重复我试图HashMap中。

但是编写代码后,它运行良好,没有错误。

HashMap<List<Integer>,Integer> final_sol=new HashMap<>();
for(int k1=0;k1<result.size();k1++){
       final_sol.put(result.get(k1),k1);
    }
    System.out.println(final_sol);

输出:

{[-1, 2, -1]=1, [0, 1, -1]=2, [-1, 0, 1]=0}

编写此代码块后,我认为我的重复键无法仅显示显示的唯一键。

然后我如何使用哈希图使该列表唯一?Fail to understand

当我使用树形图时,它无法编译并给som带来了错误。

3 个答案:

答案 0 :(得分:10)

确实,Map不保留重复的键,而Set不保留重复的元素,但是您需要了解,“重复”是根据键/元素equals()方法定义的,并且基于散列集合取决于其键/元素具有与其hashCode()方法一致的equals()方法。

现在你说

  

[-1,0,1][0,1,-1]相同。

,但不是,就List的平等定义而言,它们相同。列表元素的顺序很重要,并且要求列表以反映这一点的方式实现equals()。这就是为什么这两个列表都可能在相同的Map中显示为键,并且都可能在相同的Set中显示为元素。

  

那我如何使用哈希图使该列表唯一?

显然,订单对您而言不是很重要,因此List并不是您真正适合的模型。如果不需要容纳重复的元素,则应考虑改用Sets。标准库提供了几种实现,据我所知,其中HashSet可能最适合您的情况。如果要做需要容纳重复的元素,那么您正在寻找一个多重集。标准库没有提供实现,但是第三方可以提供几种。

  

当我使用树形图时,它无法编译并给出了一些错误。

是的,除非您提供了Comparator来确定元素的相对顺序,否则它会。 TreeMap将重复项识别为根据自然或比较器指定顺序进行比较的键。

总体来说,您想要的是一组集合或一组多重集合,而不是列表列表。我不明白您为什么要将地图引入其中。

答案 1 :(得分:2)

尝试这样的事情:

List<List<Integer>> result = Arrays.asList(
      Arrays.asList(-1, 0, 1),
      Arrays.asList(-1, 2, -1),
      Arrays.asList(0, 1, -1)
);
HashMap<Set<Integer>, List<Integer>> final_sol = new HashMap<>();

for (List<Integer> list : result) {
  final_sol.put(new HashSet<>(list), list);
}

System.out.println(final_sol.values());

您想,[-1,0,1][0,1,-1]它们是一样的,但是这并不成立,因为元素事项顺序列表。您需要设置集合才能理解平等。

但是即使[0,0,1][0,1,1]相同,也可能不是您所期望的。在这种情况下,您必须将每个列表转换为一个Map,该Map可以为您提供原始列表中相同Integer的数量。

答案 2 :(得分:0)

看来您可以使用Set<Set<Integer>>在线进行此操作。那给你[[-1, 0, 1], [-1, 2]];与[[-1, 0, 1], [-1, 2, -1]]同构,但不是您想要的结果。以下是一组三个整数的向量,这些向量与任何排列比较相等,这与您的示例一致。对于documentation,覆盖equals需要equivalence relation,并且必须要hashCode,这样a == b -> hashCode(a) == hashCode(b)

import java.lang.String;
import java.lang.Integer;
import java.util.Set;
import java.util.LinkedHashSet;

class Java {

    public static void main(String args[]) {
        Set<Three> set = new LinkedHashSet<>();
        set.add(new Three(-1, 0, 1));
        set.add(new Three(-1, 2, -1));
        set.add(new Three(0, 1, -1));
        System.out.printf("%s.\n", set);
    }

}

final class Three {
    private int a, b, c;
    public Three(final int a, final int b, final int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    @Override
    public int hashCode() { return a + b + c; }
    @Override
    public boolean equals(Object o) {
        if(this == o) return true;
        if(!(o instanceof Three)) return false;
        Three t = (Three)o;
        /* Brute force 3! = 6. */
        return a == t.a && b == t.b && c == t.c
            || a == t.a && b == t.c && c == t.b
            || a == t.b && b == t.a && c == t.c
            || a == t.b && b == t.c && c == t.a
            || a == t.c && b == t.a && c == t.b
            || a == t.c && b == t.b && c == t.a;
    }
    @Override
    public String toString() {
        return "["+a+","+b+","+c+"]";
    }
}

这产生了

[[-1,0,1], [-1,2,-1]].

编辑:以下内容代替了上面的代码,替换了三个整数的向量集,这些向量放在集合中时比较相等,这也与您的示例一致。

    /** Hashcode is the sum of the unique numbers. */
    @Override
    public int hashCode() {
        int h = a;
        if(a != b) h += b;
        if(c != a && c != b) h += c;
        return h;
    }
    @Override
    public boolean equals(Object o) {
        if(this == o) return true;
        if(!(o instanceof Three)) return false;
        Three t = (Three)o;
        /* t \in this && this \in t. */
        return (a == t.a || a == t.b || a == t.c)
            && (b == t.a || b == t.b || b == t.c)
            && (c == t.a || c == t.b || c == t.c)
            && (t.a == a || t.a == b || t.a == c)
            && (t.b == a || t.b == b || t.b == c)
            && (t.c == a || t.c == b || t.c == c);
    }