Java HashSet <String>的contains()方法testingstring或对象标识是否相等?
比方说,我在Java中有这个代码:
HashSet<String> wordSet = new HashSet<String>(); String a = "hello"; String b = "hello"; wordSet.add(a);
会wordSet.contains(b);
返回true
或false
? 据我所知, a
和b
指的是不同的对象,即使它们的值是相同的。 所以contains()
应该返回false
。 但是,当我运行这个代码时,它返回true
。 只要b
包含值"hello"
它将始终返回true
无论String对象b
来自哪里? 我总是保证这一点? 如果不是,我什么时候不能保证呢? 那么如果我想用Strings以外的对象做类似的事情呢?
它使用equals()
来比较数据。 下面是来自javadoc的Set
(e == null?e2 == null:e.equals(e2)),则将指定的元素e添加到此集合中。
String的equals()
方法通过字符比较来进行字符。 从String的javadoc
当且仅当参数不是null并且是表示与此对象相同的字符序列的String对象时,结果为true
其实,HashSet 既不 。
它的实现使用了一个HashMap,下面是相关的代码来确定这个集合是否contains()
(实际上它在HashMap的getEntry()方法中):
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
哪一个:
- 要求哈希值相等
- 要求对象相等或
equals()
返回true
答案是“是”: wordSet.contains(b)
将始终返回true
实际上,a和b都是指向同一个对象,因为Java中的string文字是自动实现的。
两件事情:
-
除非它调用equals()方法来确定相等,否则一个集合将会非常无用。 wordset.contains(b)将返回true,因为a.equals(b)== true。
-
你不能完全确定a和b指向不同的对象。 签出String.intern()了解更多详情。
最终contains
将检查equals
方法,而不是它的对象idvalidation包含方法。 因此equals
方法将被调用contains
调用。 这是contains
方法的调用结构。
private transient HashMap<E,Object> map; public boolean contains(Object o) { return map.containsKey(o); } public boolean containsKey(Object key) { return getEntry(key) != null; } final Entry<K,V> getEntry(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
平等。 在你的例子中, contains()
返回true,因为HashSet检查a.equals( b )
。