检查数组是否存在于HashSet

检查数组是否存在于HashSet

本文介绍了检查数组是否存在于HashSet< int []>中.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何检查 HashSet 中是否存在数组?

How do I check if an array exists in 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);

输出:

它并没有利用 HashSet 的快速查找.如评论中所述,这是不可能的,因为数组的等于 hashCode 并不认为包含相同数字且顺序相同的数组是相等的.数组仅被视为等于其自身.因此,我们需要对集合进行线性搜索,以找到包含相同数字的数组(如果存在一个数字).我正在为此使用流管道.您也可以使用循环.

It doesn’t exploit the fast look up of a HashSet though. As noted in the comments, this is not possible because equals and hashCode for arrays doesn’t consider arrays containing the same numbers in the same order equal. An array is only considered equal to itself. We therefore need a linear search through the set to find the array containing the same numbers if there is one. I am using a stream pipeline for that. You may alternatively use a loop.

要利用 HashSet 中的快速查找,您可以使用列表而不是数组:

To exploit the fast lookup in a HashSet you may use lists instead of arrays:

    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 原语,通常占用更多空间.

The List<Integer> approach has a space penalty, though, since it is storing Integer objects rather than int primitives, which generally takes up more space.

如果上述方法仍然不够有效(仅用于大多数目的),则可以使用自己的数字类:

If the above still isn’t efficient enough — which it is for the vast majority of purposes — you may use your own class for the numbers:

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()的时间效率.

Now we have the space efficiency of the original int array approach, nearly, and the time efficiency of the hashCode().

正如评论中的蓬松笔记所示,还有更多选择,您可能需要自己研究一些.我在这里引用评论:

As fluffy notes in the comments, there are still more options, and you may want to research some on your own. I am quoting the comments here:

public final class IntArrayKey {
    private final int[];
    ...
}

(遭受可能的阵列突变或防御性阵列克隆的困扰),或像

(suffers from possible array mutation or defensive array cloning), orsomething like

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 推动而不是 List< Integer> (例如 IntList 正确覆盖等于 hashCode ).不确定是否值得现在添加所有可能的解决方案(也许还有更多?).:)

And probably one more solution I can think of is usingfastutil orTrove instead ofList<Integer> (e.g.IntListthat overrides equals and hashCode properly). Not sure it worthadding all possible solutions (perhaps there are more?) now. :)

这篇关于检查数组是否存在于HashSet&lt; int []&gt;中.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!