Java 检查集合是否包含对象,通过引用进行比较

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22557042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:28:44  来源:igfitidea点击:

Check if a collection contains an object, comparing by reference

javacollections

提问by Paolo Fulgoni

The Collection.contains()method check if a collection contains a given object, using the .equals()method to perform the comparison.

所述Collection.contains()方法检查如果一个集合包含一个给定的对象,使用该.equals()方法来执行比较。

From Java7 Javadoc:

来自 Java7 Javadoc:

boolean contains(Object o)

Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e)).

布尔包含(对象 o)

如果此集合包含指定的元素,则返回 true。更正式地说,当且仅当此集合包含至少一个元素 e 使得 (o==null ? e==null : o.equals(e)) 时才返回 true。

Is there a smart way to check if a collection contains an object o, but comparing by reference instead (i.e. o==e)?

有没有一种聪明的方法来检查集合是否包含对象o,而是通过引用进行比较(即o==e)?

Of course I can iterate through the collection and make the check, I'm looking for an existing function which can do that.

当然,我可以遍历集合并进行检查,我正在寻找可以执行此操作的现有函数。

Clarifications:

说明:

  • I want to perform this operation regardlessthe equals()implementation of the object in the collection.
  • I don't want to change the objects in the collection nor the collection itself.
  • 无论equals()集合中对象的实现如何,我都想执行此操作。
  • 我不想更改集合中的对象或集合本身。

Edit:

编辑:

Even though my question is about a general solution for Collectionimplementations, specific cases for Collectionsub-interfaces would also be appreciated.

即使我的问题是关于实现的一般解决方案,也将不胜感激子接口的Collection特定情况Collection

采纳答案by arshajii

For those of us using Java 8, Collection#stream()is a clean option:

对于我们这些使用 Java 8 的人来说,这Collection#stream()是一个干净的选择:

collection.stream().anyMatch(x -> x == key)

回答by Suresh Atta

There is no way to check that the way you are trying to do. Without iterating through collection you cannot check that the object point to same reference or not.

没有办法检查您正在尝试的方式。如果不遍历集合,就无法检查对象是否指向相同的引用。

AFAIK, No (At least a clean way).

AFAIK,不(至少是一种干净的方式)。

回答by Germann Arlington

When you create a class you should override at least equals(and hashCode) methods.
If you implement your equalsmethod to compare by reference you will achieve your goal.

当您创建一个类时,您应该至少覆盖equals(和hashCode)方法。
如果您实施您的equals方法以通过引用进行比较,您将实现您的目标。

回答by fge

There is some kind of workaround...

有一种解决方法......

You can use an IdentityHashMap, with Voidas values (or whatever else -- your choice). You'd then use contains()on its .keySet()to check the presence of an element (or .containsKey()on the map directly).

您可以使用IdentityHashMap, with Voidas 值(或其他任何 - 您的选择)。然后您将使用contains().keySet()来检查元素的存在(或.containsKey()直接在地图上)。

A second workaround would be to use Guava and Equivalence.identity(); however your Collectionwill have to have elements of type Equivalence.Wrapper<X>and you'd have to wrapbefore checking...

第二种解决方法是使用番石榴和Equivalence.identity();但是,您Collection必须拥有 type 元素,Equivalence.Wrapper<X>并且必须wrap在检查之前...



Curiously enough, the JDK does not provide an IdentityHashSet. This is rather strange considering that the internal implementation of HashSetuses a HashMap, so one has to wonder why they didn't do the same for IdentityHashMap...

奇怪的是,JDK 没有提供IdentityHashSet. 考虑到内部实现HashSet使用 a HashMap,这很奇怪,所以人们不得不想知道为什么他们没有为IdentityHashMap...



Side note: the documentation of Collectionis misleading; not all Collectionimplementations rely on .equals(). See, for instance, SortedSetor SortedMap. And, of course, IdentityHashMap.

旁注: 的文档Collection具有误导性;并非所有Collection实现都依赖于.equals(). 例如,请参阅SortedSetSortedMap。而且,当然,IdentityHashMap

回答by OldCurmudgeon

You should be able to do it by wrapping the object in your own object which implements the equalsyou are looking for.

您应该能够通过将对象包装在您自己的对象中来实现equals您正在寻找的对象。

Something like:

就像是:

private class Identical<T> {
    final T held;

    Identical (T hold) {
        held = hold;
    }

    public boolean equals(Object it) {
        return it != null && held == it;
    }
}

Obviously you would have to take control of adding items to the collection and wrap each one in one of these.

显然,您必须控制向集合中添加项目并将每个项目包装在其中之一中。

You could wrap the map like this:

您可以像这样包装地图:

static class ReferenceHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {

    private final Map<K, Identical<V>> map = new HashMap<>();

    private static class Identical<T> {

        final T held;

        Identical(T hold) {
            held = hold;
        }

        @Override
        public boolean equals(Object it) {
            return it != null && held == it;
        }

        @Override
        public int hashCode() {
            return held.hashCode();
        }
    }

    @Override
    public V get(Object key) {
        Identical<V> value = map.get(key);
        return value == null ? null : value.held;
    }

    @Override
    public V put(K key, V value) {
        Identical<V> replaced = map.put(key, new Identical<>(value));
        return replaced == null ? null : replaced.held;
    }

    private class MyEntry implements Map.Entry<K, V> {

        private final K key;
        private V value;

        public MyEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            V old = this.value;
            this.value = value;
            return old;
        }
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        Set<Entry<K, V>> entries = new HashSet<>();
        for (Entry<K, Identical<V>> entry : map.entrySet()) {
            entries.add(new MyEntry(entry.getKey(), entry.getValue().held));
        }
        return entries;
    }

}

回答by Paolo Fulgoni

The answers point out that it is not possible in a clean wayto perform the desired check.

答案指出不可能以干净的方式执行所需的检查。

So this is a possible implementation of such requested function:

所以这是这种请求功能的可能实现:

/**
 * Returns {@code true} if the collection contains the specified element.
 * <p>
 * More formally, returns {@code true} if and only if this collection
 * contains at least one element {@code x} such that {@code x == element}.
 * <p>
 * Note: {@link Collection#contains(Object)} works differently because uses
 * {@link Object#equals(Object)} for comparison
 * 
 * @param collection
 *            collection where to look for the element
 * @param element
 *            element whose presence in this collection is to be tested
 * @return {@code true} if this collection contains the specified element
 * @throws NullPointerException
 *             if {@code collection} is null
 */
public static <T> boolean containsReferenceTo(Collection<T> collection,
        T element) {
    if (collection == null)
        throw new NullPointerException("collection cannot be null");

    for (T x : collection) {
        if (x == element) {
            return true;
        }
    }
    return false;
}

NOTE:this may be optimized for some specific Collectionimplementations.

注意:这可能会针对某些特定Collection实现进行优化。