Java HashSet <String>的contains()方法testingstring或对象标识是否相等?

比方说,我在Java中有这个代码:

HashSet<String> wordSet = new HashSet<String>(); String a = "hello"; String b = "hello"; wordSet.add(a); 

wordSet.contains(b); 返回truefalse ? 据我所知, ab指的是不同的对象,即使它们的值是相同的。 所以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文字是自动实现的。

两件事情:

  1. 除非它调用equals()方法来确定相等,否则一个集合将会非常无用。 wordset.contains(b)将返回true,因为a.equals(b)== true。

  2. 你不能完全确定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 )