2012-02-23 10 views
5

Jeśli dwa identyczne String nie są identyczne, to dlaczego mogę używać łańcuchów jako kluczy w HashMap bez używania tego samego obiektu String?Dlaczego mogę używać ciągów jako kluczy w HashMap?

String s1 = "Test"; 
String s2 = "Test"; 

System.out.println(s1 == s2); // should be false 
System.out.println(s1.equals(s2)); // should be true 

HashMap<String, String> map = new HashMap(); 
map.put(s1, "foo"); 
System.out.println(map.get(s2)); // should be "foo"--but why? 

Czy HashMap mieć jakieś szczególne zachowanie dla String obiektów? Jeśli nie, dlaczego dwa "różne" ciągi mogą być użyte do umieszczenia i uzyskania wartości z hasza?

+6

Zauważ, że 's1 == s2' będzie miało wartość' true' z powodu interwencji ciągów znaków. –

+0

Dlaczego więc standardową praktyką jest używanie '.equals()' do porównywania 'String'ów? –

+1

@ Ted Hopp s1 == s2 będzie prawdą z powodu * stałej puli *. – EJP

Odpowiedz

14

HashMap porównuje obiekty przez wywołanie equals() i hashCode().
String zastępuje te metody w celu porównania według wartości.

4

Jeśli dwóch ciągów, które są takie same nie są w rzeczywistości równa

Ale są. Są one równe pod metodą equals() i jest to technika określona dla testowania równości w interfejsie Map.

System.out.println(s1 == s2); // should be false 

Ale to nie jest fałsz! Oba odnoszą się do tego samego ciągu z powodu stałego łączenia przez kompilator.

2

Gdy wewnętrznie porównuje klucz HashMap, używa metody equals(), a nie ==. Tak obiekt równość jest w porządku za kluczowy mecz, równości odniesienia nie jest wymagane, jeżeli equals() jest przesłonięta (jak w przypadku java.lang.String.)

5

Generalnie można używać obiektów String ponieważ HashMap wykorzystuje equals() i nie == do testowania kluczowa równość.

1

System.out.println (s1 == s2); // powinien być fałszywy

Nie powinien. Kompilator Java może zoptymalizować i skierować dwa ciągi do tej samej lokalizacji.

Aktualizacja

public class Test { 

    public static void main(String... args) { 
     String s1 = "abc"; 
     String s2 = "abc"; 

     System.out.println(s1 == s2); 
    } 

} 

Wyjście

javac Test.java 
java Test 
> true 
+0

Źle, źle, źle. Możesz łatwo to udowodnić za pomocą prostego kodu. – duffymo

+3

Nie, nie jest źle. Nazywa się "interning". –

+2

Przez "może zoptymalizować" myślę, że masz na myśli "musi zoptymalizować", zakładając, że kompilator Java jest zgodny ze specyfikacją. http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5 – yshavit

-2

naprawdę powinniśmy wrócić do podstawowego pierwszy. nauka

komputer fundamentalna:

== porównuje adres pamięci (referencyjną)

.equals porównuje wartość przechowywaną w pamięci adres

java podstawowego. istnieje tylko jedna kopia obiektu typu string w całym jvm

+3

Niemal każda linia w odpowiedzi jest subtelnie lub rażąco błędna. – SLaks

+0

To nie są "podstawy informatyki". Są podstawami * Java *. Odwołanie do Java niekoniecznie jest adresem pamięci. W przypadku użycia konstrukcji 'new String (...)' może istnieć wiele kopii ciągu. – EJP

Powiązane problemy