检查HashSet<int[]>中是否存在数组
如何检查数组是否存在于 a 中HashSet?
例如:
int[] a = new int[]{0, 0};
HashSet<int[]> set = new HashSet<>();
set.add(a);
然后:
int[] b = new int[]{0, 0};
set.contains(b); // ===> true
回答
使用数组
int[] a = new int[] { 0, 0 };
HashSet<int[]> set = new HashSet<>();
set.add(a);
int[] b = new int[] { 0, 0 };
boolean contains = set.stream().anyMatch(c -> Arrays.equals(c, b));
System.out.println("Contains? " + contains);
输出:
包含?真的
它没有利用 a 的快速查找HashSet。正如评论中所指出的,这是不可能的,因为equalsand hashCodefor 数组不认为包含相同顺序的相同数字的数组相等。一个数组只被认为等于它自己。因此,我们需要对集合进行线性搜索,以找到包含相同数字的数组(如果有)。我为此使用了流管道。您也可以使用循环。
更快:使用列表
要利用 a 中的快速查找,HashSet您可以使用列表而不是数组:
List<Integer> a = List.of(0, 0);
HashSet<List<Integer>> set = new HashSet<>();
set.add(a);
List<Integer> b = List.of(0, 0);
System.out.println("Contains? " + set.contains(b));
包含?真的
List<Integer>但是,这种方法有空间损失,因为它存储的是Integer对象而不是int基元,基元通常会占用更多空间。
既节省空间又节省时间:开发自定义类
如果以上仍然不够有效——这是用于绝大多数目的——你可以使用你自己的类来计算数字:
public class IntArray {
int[] elements;
public IntArray(int... elements) {
// Make a defensive copy to shield from subsequent modifications of the original array
this.elements = Arrays.copyOf(elements, elements.length);
}
@Override
public int hashCode() {
return Arrays.hashCode(elements);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IntArray other = (IntArray) obj;
return Arrays.equals(elements, other.elements);
}
}
这将允许:
IntArray a = new IntArray(0, 0);
HashSet<IntArray> set = new HashSet<>();
set.add(a);
IntArray b = new IntArray(0, 0);
System.out.println("Contains? " + set.contains(b));
包含?真的
现在我们有了原始int数组方法的空间效率,几乎,以及hashCode().
更多选择(谢谢,蓬松)
作为评论中的蓬松注释,还有更多选择,您可能需要自己研究一些。我在这里引用评论:
另外,如果我没有错的话,可以有两个基于密钥的解决方案:比如
public final class IntArrayKey { private final int[]; ... }(遭受可能的阵列突变或防御性阵列克隆),或类似
public final class Key<T> { private final Predicate<T> equals; private final IntSupplier hashCode; public static Key<int[]> of(final int[] array) { return new Key<>(that -> Arrays.equals(array, that), () -> Arrays.hashCode(array)); }保持通用。
也许我能想到的另一种解决方案是使用
fastutil或
Trove而不是
List<Integer>(例如
IntList
,覆盖equals并hashCode正确)。现在不确定是否值得添加所有可能的解决方案(也许还有更多?)。:)