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 ) 。