我有一个清单清单。列表中有一个列表。
[[-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带来了错误。
答案 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);
}