java 中的字符串相等性检查
String equality check in java
下面两种说法的区别:
String s = "Hello";
String s = new String("Hello');
在第一个语句中,赋值运算符-用于将字符串文字赋值给String变量s
。在这种情况下; JVM
首先检查字符串常量池中是否已经存在同一个对象。如果它可用,那么它会创建另一个对它的引用。如果同一个对象不可用,则创建另一个内容为"Hello"的对象,存入字符串常量池
在second语句中,new
运算符用于创建字符串对象。在这种情况下,JVM
总是在不查看字符串常量池的情况下创建一个新对象。
我对下面提供的代码的怀疑是语句的输出
System.out.println(a.hashCode() + " " + b.hashCode());
根据规则,这两个对象应该有不同的内存位置,但是它们的哈希码都显示 true
import java.util.HashMap;
import java.util.Map;
class TestStringEquality
{
public static void main (String[] args)
{
String a = new String("abcd");
String b = new String("abcd");
System.out.println(a == b);
System.out.println(a.hashCode() + " " + b.hashCode());
System.out.println(a.equals(b));
Map<String, String> map = new HashMap<>();
map.put(new String("abcd"), "abcd");
map.put(new String("abcd"), "wxyz");
System.out.println(map);
}
}
我得到的输出如下:
false
2987074 2987074
true
{abcd=wxyz}
根据 API sheet 在 https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode--
字符串哈希码中使用的公式取决于字符串的长度和内容,而不是内存位置。因此,具有不同内存位置的两个相同字符串应该给出相同的哈希码。
我认为您对普通堆内存和字符串常量池感到困惑。当您检查是否相等时,JVM 会为您获取存储在正常堆内存中的对象,该对象是相同的。它们仅在字符串常量池中不同。这就是为什么 '==' returns false 因为位置在字符串常量池中不同,因为副本具有不同的引用但等于 returns true 因为两者都是相同的类型并且包含相似的字符串。
Java 有一个名为 String Pool
的概念。程序中使用过的每一个字符串都会作为缓存机制存储在池中。
例如下面的代码:
String a = "Whosebug"; // Java will push Whosebug into string pool
String b = "Whosebug"; // Java will get address of "Whosebug" object in string pool and assigned to b.
在Java中,程序员不必直接使用指针。但是,指针仍然存在。当使用运算符“==”时,原始 data-type 变量,如 int、short … 将根据它们的值进行比较。但是在 String 中,Java 将根据它们的地址进行比较。
这就是以下行 return 为真的原因:
System.out.println(a == b); // true
然而,当您调用new String(...)
时,Java会创建一个新的字符串对象。它不会查看字符串池来检查字符串的值是否已存储在字符串池中。这就是两个变量具有相同值的原因,它们的地址仍然不同,因此“==”运算符将 return false.
String a = "Whosebug";
String b = new String("Whosebug"); // new string object. not use old one in String Pool.
System.out.println(a == b); // False. because they have different addresses.
由于String Pool机制,我们必须在比较两个对象时使用equals
方法。通过这样做,我们不需要关心 String 对象是如何构建的。所以下面的代码总是 return true:
String a = "Whosebug";
String b = "Whosebug"; // use same object as a
String c = new String("Whosebug"); // create new string
System.out.println(a.equals(b)); // true
System.out.println(a.equals(b)); // true
System.out.println(a.equals(c)); // true
关于哈希码,Java将使用哈希函数从字符串的字符中计算出值。这样无论字符串如何构建,如果 2 个字符串的值相等,它们将具有相同的哈希码。
String a = "Whosebug";
String b = "Whosebug"; // use same object as a
String c = new String("Whosebug"); // create new string
System.out.println(a.hashCode() == b.HashCode()); // true
System.out.println(a.hashCode() == c.HashCode()); // true
根据讨论,我们可以得出以下结论。如果 2 个字符串具有相同的哈希码,我们不能断言运算符“==” return 为真。因为它们可能是相同的值,但是它们在堆内存上是不同的对象。
但反之亦然。如果 2 个字符串指向相同的地址,它们将具有相同的值,因此具有相同的哈希码。
有趣的问题:如果两个字符串的哈希码相等,我们可以假设这两个字符串相等吗?
hashCode() 实现 "Object" class returns 底层内存位置。
"String" 的 hashCode() 实现覆盖了对象中的 hashCode()。 Returns 此字符串的哈希码。 String 对象的哈希码计算为
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
另外,这让程序员的生活更轻松。例如,我们可以使用硬编码字符串键查询 Map,而不是保留原始键对象。
这个字符串相等你可以用hashcode方法。
但是,为了获得更好的性能,请使用
String firstString = "string1";
String secondString = "String1";
println(" it will return boolean " + firstString.equal(secondString ) + " "); //false
println(" it will return boolean " + firstString.equalIgnoreCase(secondString ) + " "); //true
下面两种说法的区别:
String s = "Hello";
String s = new String("Hello');
在第一个语句中,赋值运算符-用于将字符串文字赋值给String变量s
。在这种情况下; JVM
首先检查字符串常量池中是否已经存在同一个对象。如果它可用,那么它会创建另一个对它的引用。如果同一个对象不可用,则创建另一个内容为"Hello"的对象,存入字符串常量池
在second语句中,new
运算符用于创建字符串对象。在这种情况下,JVM
总是在不查看字符串常量池的情况下创建一个新对象。
我对下面提供的代码的怀疑是语句的输出
System.out.println(a.hashCode() + " " + b.hashCode());
根据规则,这两个对象应该有不同的内存位置,但是它们的哈希码都显示 true
import java.util.HashMap;
import java.util.Map;
class TestStringEquality
{
public static void main (String[] args)
{
String a = new String("abcd");
String b = new String("abcd");
System.out.println(a == b);
System.out.println(a.hashCode() + " " + b.hashCode());
System.out.println(a.equals(b));
Map<String, String> map = new HashMap<>();
map.put(new String("abcd"), "abcd");
map.put(new String("abcd"), "wxyz");
System.out.println(map);
}
}
我得到的输出如下:
false
2987074 2987074
true
{abcd=wxyz}
根据 API sheet 在 https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode-- 字符串哈希码中使用的公式取决于字符串的长度和内容,而不是内存位置。因此,具有不同内存位置的两个相同字符串应该给出相同的哈希码。
我认为您对普通堆内存和字符串常量池感到困惑。当您检查是否相等时,JVM 会为您获取存储在正常堆内存中的对象,该对象是相同的。它们仅在字符串常量池中不同。这就是为什么 '==' returns false 因为位置在字符串常量池中不同,因为副本具有不同的引用但等于 returns true 因为两者都是相同的类型并且包含相似的字符串。
Java 有一个名为 String Pool
的概念。程序中使用过的每一个字符串都会作为缓存机制存储在池中。
例如下面的代码:
String a = "Whosebug"; // Java will push Whosebug into string pool
String b = "Whosebug"; // Java will get address of "Whosebug" object in string pool and assigned to b.
在Java中,程序员不必直接使用指针。但是,指针仍然存在。当使用运算符“==”时,原始 data-type 变量,如 int、short … 将根据它们的值进行比较。但是在 String 中,Java 将根据它们的地址进行比较。
这就是以下行 return 为真的原因:
System.out.println(a == b); // true
然而,当您调用new String(...)
时,Java会创建一个新的字符串对象。它不会查看字符串池来检查字符串的值是否已存储在字符串池中。这就是两个变量具有相同值的原因,它们的地址仍然不同,因此“==”运算符将 return false.
String a = "Whosebug";
String b = new String("Whosebug"); // new string object. not use old one in String Pool.
System.out.println(a == b); // False. because they have different addresses.
由于String Pool机制,我们必须在比较两个对象时使用equals
方法。通过这样做,我们不需要关心 String 对象是如何构建的。所以下面的代码总是 return true:
String a = "Whosebug";
String b = "Whosebug"; // use same object as a
String c = new String("Whosebug"); // create new string
System.out.println(a.equals(b)); // true
System.out.println(a.equals(b)); // true
System.out.println(a.equals(c)); // true
关于哈希码,Java将使用哈希函数从字符串的字符中计算出值。这样无论字符串如何构建,如果 2 个字符串的值相等,它们将具有相同的哈希码。
String a = "Whosebug";
String b = "Whosebug"; // use same object as a
String c = new String("Whosebug"); // create new string
System.out.println(a.hashCode() == b.HashCode()); // true
System.out.println(a.hashCode() == c.HashCode()); // true
根据讨论,我们可以得出以下结论。如果 2 个字符串具有相同的哈希码,我们不能断言运算符“==” return 为真。因为它们可能是相同的值,但是它们在堆内存上是不同的对象。
但反之亦然。如果 2 个字符串指向相同的地址,它们将具有相同的值,因此具有相同的哈希码。
有趣的问题:如果两个字符串的哈希码相等,我们可以假设这两个字符串相等吗?
hashCode() 实现 "Object" class returns 底层内存位置。
"String" 的 hashCode() 实现覆盖了对象中的 hashCode()。 Returns 此字符串的哈希码。 String 对象的哈希码计算为
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
另外,这让程序员的生活更轻松。例如,我们可以使用硬编码字符串键查询 Map,而不是保留原始键对象。
这个字符串相等你可以用hashcode方法。 但是,为了获得更好的性能,请使用
String firstString = "string1";
String secondString = "String1";
println(" it will return boolean " + firstString.equal(secondString ) + " "); //false
println(" it will return boolean " + firstString.equalIgnoreCase(secondString ) + " "); //true