Java中的字符串实习和HashSet

时间:2018-11-07 17:31:33

标签: java string

我已经阅读了有关字符串实习的信息,其中字符串文字被重用,而使用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

4 个答案:

答案 0 :(得分:0)

HashSet使用 equality 保留一组唯一的值,而不是 identity (即,如果两个对象彼此equals,但没有==HashSet只会保留其中一个)。

您可以通过使用JDK的IdentityHashMap和所有键之间共享的虚拟值来实现使用标识而不是相等的集合,类似于HashSet基于HashMap的方式

答案 1 :(得分:0)

  

我已经读过有关字符串实习的信息,在其中字符串的文字被重用,而使用new创建的String对象没有被重用。当我为它们的相等性打印真假时,可以在下面看到。具体来说,(p1 == p2)!= p3,所以有两个对象,一个由p1和p2指向,另一个由p3指向。但是,当我将它们添加到HashSet时,都被认为是相同的。我期望a.size()返回2,但它返回1。

仅当您使用==比较String时,这是正确的,使用equals()方法进行比较时结果是不同的。 (有疑问,您可以测试)。

当添加到HashSet中时,使用的比较方法是equals()作为对象的适当方法。因此,p1p2p3是相等的。

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

在这种情况下,我建议您学习如何使用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会比较字符串值而不是引用。而且HashSet会看到所有相同的内容,因为它使用的方法.hashCode.equals类似,因为它会生成 string值的哈希值。 / p>

希望这可以消除一些困惑!