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
Check if a collection contains an object, comparing by reference
提问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 Collection
implementations, specific cases for Collection
sub-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 equals
method 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 Void
as 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 Void
as 值(或其他任何 - 您的选择)。然后您将使用contains()
它.keySet()
来检查元素的存在(或.containsKey()
直接在地图上)。
A second workaround would be to use Guava and Equivalence.identity()
; however your Collection
will have to have elements of type Equivalence.Wrapper<X>
and you'd have to wrap
before 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 HashSet
uses 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 Collection
is misleading; not all Collection
implementations rely on .equals()
. See, for instance, SortedSet
or SortedMap
. And, of course, IdentityHashMap
.
旁注: 的文档Collection
具有误导性;并非所有Collection
实现都依赖于.equals()
. 例如,请参阅SortedSet
或SortedMap
。而且,当然,IdentityHashMap
。
回答by OldCurmudgeon
You should be able to do it by wrapping the object in your own object which implements the equals
you 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 Collection
implementations.
注意:这可能会针对某些特定Collection
实现进行优化。