Проверка равенства строк в Java - PullRequest
0 голосов
/ 25 июня 2019

Разница между следующими двумя утверждениями:

  1. String s = "Hello";
  2. String s = new String("Hello');

В операторе first оператор присваивания используется для присвоения строкового литерала переменной 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}

Ответы [ 5 ]

4 голосов
/ 25 июня 2019

Согласно листу API на https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode-- формула, используемая в хеш-коде строки, зависит от длины и содержимого строки, а не от места в памяти. Поэтому две идентичные строки с разными ячейками памяти должны давать один и тот же хэш-код.

3 голосов
/ 25 июня 2019

Java имеет одну концепцию с именем String Pool.Каждая строка, использованная в программе, будет храниться в пуле в качестве механизма кеширования.

Например, код ниже:

String a = "StackOverFlow";  // Java will push StackOverFlow into string pool
String b = "StackOverFlow";  // Java will get address of "StackOverFlow" object in string pool and assigned to b.

В Java программистам не нужно напрямую работать с указателями.Тем не менее, указатели все еще здесь.При использовании оператора "==" примитивные переменные типа данных, такие как int, short ... будут сравниваться по своим значениям.Но в String Java будет сравниваться по их адресам.

По этой причине следующая строка вернет true:

System.out.println(a == b); // true

Однако, когда вы вызываете new String(...), Java создаст новый строковый объект.Он не смотрит в пул строк, чтобы проверить, сохранено ли значение строки в пуле строк или нет.По этой причине две переменные имеют одинаковое значение, они по-прежнему различаются по адресу, поэтому оператор "==" возвращает false.

String a = "StackOverFlow";
String b = new String("StackOverFlow"); // new string object. not use old one in String Pool.
System.out.println(a == b); // False. because they have different addresses. 

Из-за механизма пула строк мы должны использовать метод equals, когдасравнить два объекта.Делая это, нам не нужно заботиться о том, как строится этот объект String.Поэтому следующий код всегда возвращает true:

String a = "StackOverFlow";
String b = "StackOverFlow";  // use same object as a
String c = new String("StackOverFlow"); // 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 будет использовать хеш-функцию для вычисления значения из символов строки.Таким образом, независимо от того, как строится строка, если две строки равны по значению, они будут иметь одинаковый хеш-код.

String a = "StackOverFlow";
String b = "StackOverFlow";  // use same object as a
String c = new String("StackOverFlow"); // create new string
System.out.println(a.hashCode() == b.HashCode()); // true
System.out.println(a.hashCode() == c.HashCode()); // true

На основании обсуждения мы можем прийти к следующему выводу.Если 2 строки имеют одинаковый хеш-код, мы не можем подтвердить, что оператор "==" возвращает true.Потому что они могут иметь одинаковое значение, но они являются разными объектами в куче памяти.

Но обратное условие является правильным.Если 2 строки указывают на один и тот же адрес, они будут иметь одно и то же значение, следовательно, один и тот же хеш-код.

Интересный вопрос : Если две строки имеют одинаковые хеш-коды, можем ли мы предположить, что эти 2 строкибудет равняться?

1 голос
/ 25 июня 2019

Реализация hashCode () класса "Object" возвращает базовую ячейку памяти.

hashCode () реализация "String" переопределяет hashCode () в Object. Возвращает хеш-код для этой строки. Хеш-код для объекта String вычисляется как

s [0] * 31 ^ (n-1) + s [1] * 31 ^ (n-2) + ... + s [n-1]

Кроме того, это облегчает жизнь программистам. Например, мы можем запросить карту, используя жестко закодированный строковый ключ, вместо того, чтобы оставить исходный ключевой объект у нас.

1 голос
/ 25 июня 2019

Я думаю, вы путаетесь между обычной памятью кучи и пулом строковых констант.Когда вы проверяете на равенство, JVM извлекает вам объект, хранящийся в обычной кучной памяти, которая является одной и той же.Они отличаются только в строковом константном пуле.Вот почему «==» возвращает значение «ложь», поскольку местоположения в пуле строковых констант различны, поскольку копии имеют разные ссылки, но равны значениям «истина», поскольку оба имеют одинаковый тип и содержат одинаковую строку.

0 голосов
/ 25 июня 2019

это равенство строк вы можете использовать методом хеш-кода. но для лучшей производительности используйте

String firstString = "string1";
String secondString = "String1";
println(" it will return boolean " + firstString.equal(secondString ) + " "); //false
println(" it will return boolean " + firstString.equalIgnoreCase(secondString ) + " "); //true
...