[英]String interning and HashSet in java
我已經讀過有關字符串實習的信息,其中字符串文字被重用,而使用new
創建的String對象沒有被重用。 這可以當我打印在下面看到true
和false
為他們的平等。 具體來說, (p1==p2)!=p3
,所以有兩個對象,一個由p1
和p2
指向,另一個由p3
指向。 但是,當我將它們添加到HashSet
,它們都被認為是相同的。 我期望a.size()
返回2
,但是它返回1
。 為什么會這樣呢?
package collections;
import java.util.HashSet;
public class Col {
public static void main(String[] args) {
method1();
}
public static void method1()
{
HashSet a = new HashSet();
String p1 = "Person1";
String p2 = "Person1";
String p3 = new String("Person1");
if(p1 == p2)
System.out.println(true);
else
System.out.println(false);
if(p1 == p3)
System.out.println(true);
else
System.out.println(false);
a.add(p1);
a.add(p2);
a.add(p3);
System.out.println(a.size());
}
}
產量
true
false
1
HashSet
使用相等性來保留一組唯一的值,而不是標識 (即,如果兩個對象彼此equals
,但不==
,則HashSet
將僅保留其中一個)。
您可以通過使用JDK的IdentityHashMap
以及所有鍵之間共享的虛擬值,來實現使用身份而非相等的集合,這類似於HashSet
基於HashMap
。
我已經讀過有關字符串實習的信息,其中字符串文字被重用,而使用new創建的String對象沒有被重用。 當我為它們的相等性打印真假時,可以在下面看到。 具體來說,(p1 == p2)!= p3,所以有兩個對象,一個由p1和p2指向,另一個由p3指向。 但是,當我將它們添加到HashSet時,都被認為是相同的。 我期望a.size()返回2,但它返回1。
僅當使用==
比較String時,這才是正確的,使用equals()
方法進行比較時,結果是不同的。 (有疑問,您可以測試)。
當添加到HashSet
,使用的比較方法為equals()
作為適用於對象的方法。 因此, p1
, p2
和p3
相等。
您可以嘗試使用equals()
進行測試,它將輸出true
, true
, 1
而不是true
, false
, 1
p1和p2是字符串文字,由於字符串池,它們指向相同的值。 因此,當我們使用==比較它們時,它們是匹配的。
p3是一個字符串對象,因此當我們使用==進行匹配時,它將嘗試使用引用進行匹配,因此它給出false。
HashSet的add方法在內部調用HashMap的put方法。 HashMap的put方法使用hashCode和equals方法在HashMap中設置值。 字符串實現hashCode和equals方法,並為相同的值提供相同的hashCode。 HashSet包含唯一值,因此它僅存儲一個值。
在這種情況下,我建議學習如何使用javap
來理解代碼的編譯方式,但讓我嘗試解釋其背后的情況。
當Java編譯該類時,它將創建指令以構建該類的所謂的常量池 。 該常量池將保存對值為“ Person1”的字符串的引用。 編譯后的邏輯還將說p1
和p2
的值應設置為對該字符串(它所駐留的內存中的地址)的常量池的引用。 調用p1==p2
將返回true
因為它們在字面上具有相同的確切值。 當您調用String p3 = new String("Person1");
您要告訴Java在內存中的不同位置創建一個新字符串,這只是原始字符串的一個副本,然后將p3
的值設置為對新字符串對象所在的內存位置的引用。因此,如果您調用p1 == p3
它將返回false
因為您所說的是“ p1
在內存中的位置等於p2
在內存中的位置嗎?”
正如其他人指出的那樣,如果調用p1.equals(p3)
則它返回true
因為.equals
比較字符串值而不是references 。 HashSet會看到所有相同的內容,因為它使用了.hashCode
方法,該方法類似於.equals
,它從字符串值生成哈希值 。
希望這可以消除一些困惑!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.