Collection.contains()方法使用.equals()
方法检查集合是否包含给定对象,以执行比较。
来自Java7 Javadoc:
布尔包含(对象o)
如果此集合包含,则返回true 指定的元素。更正式地说,当且仅当这样时,返回true 集合包含至少一个元素e,使得(o == null? e == null:o.equals(e))。
是否有一种智能方法可以检查集合是否包含对象o
,而是通过引用进行比较(即o==e
)?
当然,我可以遍历整个系列并进行检查,我正在寻找能够做到这一点的现有功能。
澄清:
equals()
实现。修改
即使我的问题是关于Collection
实现的一般解决方案,也可以理解Collection
子接口的特定情况。
答案 0 :(得分:32)
对于我们这些使用Java 8的人来说,Collection#stream()
是一个干净的选择:
collection.stream().anyMatch(x -> x == key)
答案 1 :(得分:10)
有某种解决方法......
您可以使用IdentityHashMap
,Void
作为值(或其他任何 - 您的选择)。然后,您可以在其contains()
上使用.keySet()
来检查元素的存在(或直接在地图上显示.containsKey()
)。
第二种解决方法是使用Guava和Equivalence.identity()
;但是,您的Collection
必须包含Equivalence.Wrapper<X>
类型的元素,并且在检查之前您必须wrap
...
奇怪的是,JDK没有提供IdentityHashSet
。考虑到HashSet
的内部实现使用HashMap
,这是相当奇怪的,因此我们不得不想知道为什么他们对IdentityHashMap
没有做同样的事情......
附注:Collection
的文档具有误导性; 并非所有Collection
实施都依赖于.equals()
。例如,请参阅SortedSet
或SortedMap
。当然还有IdentityHashMap
。
答案 2 :(得分:3)
无法检查您尝试的方式。如果不迭代集合,则无法检查对象是否指向相同的引用。
AFAIK,否(至少是一种干净的方式)。
答案 3 :(得分:3)
答案指出无法以干净的方式执行所需的检查。
所以这是这种请求函数的可能实现:
/**
* 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;
}
注意:强>
这可以针对某些特定的Collection
实现进行优化。
答案 4 :(得分:2)
创建课程时,您应该至少覆盖equals
(和hashCode
)方法
如果您通过引用实施equals
方法进行比较,那么您将实现目标。
答案 5 :(得分:0)
您应该可以通过将对象包装在您自己的对象中来实现,该对象实现了您正在寻找的equals
。
类似的东西:
private class Identical<T> {
final T held;
Identical (T hold) {
held = hold;
}
public boolean equals(Object it) {
return it != null && held == it;
}
}
显然,您必须控制将项目添加到集合中,并将每个项目包装在其中一个项目中。
你可以像这样包装地图:
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;
}
}