繁体   English   中英

Java中的字符串实习和HashSet

[英]String interning and HashSet in java

我已经读过有关字符串实习的信息,其中字符串文字被重用,而使用new创建的String对象没有被重用。 这可以当我打印在下面看到truefalse为他们的平等。 具体来说, (p1==p2)!=p3 ,所以有两个对象,一个由p1p2指向,另一个由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()作为适用于对象的方法。 因此, p1p2p3相等。

您可以尝试使用equals()进行测试,它将输出truetrue1而不是truefalse1

p1和p2是字符串文字,由于字符串池,它们指向相同的值。 因此,当我们使用==比较它们时,它们是匹配的。

p3是一个字符串对象,因此当我们使用==进行匹配时,它将尝试使用引用进行匹配,因此它给出false。

HashSet的add方法在内部调用HashMap的put方法。 HashMap的put方法使用hashCode和equals方法在HashMap中设置值。 字符串实现hashCode和equals方法,并为相同的值提供相同的hashCode。 HashSet包含唯一值,因此它仅存储一个值。

在这种情况下,我建议学习如何使用javap来理解代码的编译方式,但让我尝试解释其背后的情况。

当Java编译该类时,它将创建指令以构建该类的所谓的常量池 该常量池将保存对值为“ Person1”的字符串的引用。 编译后的逻辑还将说p1p2的值应设置为对该字符串(它所驻留的内存中的地址)的常量池的引用。 调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM