检查集合是否包含对象,按引用进行比较
Collection.contains()方法使用.equals()
()方法检查集合是否包含给定对象以执行比较。
来自Java7 Javadoc:
boolean contains(Object o)
如果此collection包含指定的元素,则返回true。 更正式地,当且仅当此集合包含至少一个元素e时才返回true(o == null?e == null:o.equals(e))。
有没有一种聪明的方法可以检查集合是否包含对象o
,而是通过引用进行比较(即o==e
)?
当然我可以遍历集合并进行检查,我正在寻找可以做到这一点的现有function。
澄清:
- 我想执行此操作, 无论集合中对象的
equals()
实现如何 。 - 我不想更改集合中的对象或集合本身。
编辑:
即使我的问题是关于Collection
实现的一般解决方案,也可以理解Collection
子接口的特定情况。
对于我们这些使用Java 8的人来说, Collection#stream()
是一个干净的选择:
collection.stream().anyMatch(x -> x == key)
有某种解决方法……
您可以使用IdentityHashMap
,将Void
作为值(或其他任何 – 您的选择)。 然后,您可以在其.keySet()
contains()
上使用contains()
来检查元素的存在(或直接在地图上显示.containsKey()
)。
第二种解决方法是使用Guava和Equivalence.identity()
; 但是你的Collection
必须有Equivalence.Wrapper
类型的元素,你必须在检查前wrap
…
奇怪的是,JDK没有提供IdentityHashSet
。 考虑到HashSet
的内部实现使用HashMap
,这是相当奇怪的,所以我们不得不想知道为什么他们不对IdentityHashMap
做同样的事情……
附注: Collection
的文档具有误导性; 并非所有Collection
实现都依赖于.equals()
。 例如,请参阅SortedSet
或SortedMap
。 当然还有IdentityHashMap
。
无法检查您尝试的方式。 如果不迭代集合,则无法检查对象是否指向相同的引用。
AFAIK,否( 至少是干净的方式 )。
答案指出,不可能以干净的方式执行所需的检查。
所以这是这种请求函数的可能实现:
/** * Returns {@code true} if the collection contains the specified element. * * More formally, returns {@code true} if and only if this collection * contains at least one element {@code x} such that {@code x == element}. *
* 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 boolean containsReferenceTo(Collection 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
实现进行了优化。
创建类时,应至少重写equals
(和hashCode
)方法。
如果您实施equals
方法以通过引用进行比较,您将实现目标。
您应该能够通过将对象包装在您自己的对象中来实现,该对象实现了您正在寻找的equals
。
就像是:
private class Identical { final T held; Identical (T hold) { held = hold; } public boolean equals(Object it) { return it != null && held == it; } }
显然,您必须控制向集合中添加项目并将其中的每个项目包装在其中。
你可以像这样包装地图:
static class ReferenceHashMap extends AbstractMap implements Map { private final Map> map = new HashMap<>(); private static class Identical { 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 value = map.get(key); return value == null ? null : value.held; } @Override public V put(K key, V value) { Identical replaced = map.put(key, new Identical<>(value)); return replaced == null ? null : replaced.held; } private class MyEntry implements Map.Entry { 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> entrySet() { Set> entries = new HashSet<>(); for (Entry> entry : map.entrySet()) { entries.add(new MyEntry(entry.getKey(), entry.getValue().held)); } return entries; } }
- Hibernate无法初始化代理 – 没有Session
- Maven spring boot使用参数运行调试
- inter jvm communication
- 在Integer上同步时对notify()的IllegalMonitorStateException
- JAVA:二叉树
- 如何从tomcat提供静态内容
- ClassCastException:org.apache.xerces.parsers.XIncludeAwareParserConfiguration无法强制转换为org.apache.xerces.xni.parser.XMLParserConfiguration
- 私有成员访问Java
- Spring – 点 – 注释后的路径变量截断