2012-02-23 57 views
5

Nếu hai String s giống nhau không thực sự giống nhau, thì tại sao tôi có thể sử dụng các chuỗi làm khóa trong một HashMap mà không sử dụng cùng một đối tượng String?Tại sao tôi có thể sử dụng Strings làm khóa trong 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? 

HashMap có một số hành vi đặc biệt cho String đối tượng không? Nếu không, tại sao có thể sử dụng hai chuỗi "khác nhau" để đặt và nhận giá trị từ băm?

+6

Lưu ý rằng 's1 == s2' sẽ là' true' do chuỗi ký tự. –

+0

Vậy tại sao thực hành tiêu chuẩn lại sử dụng '.equals()' để so sánh 'String'? –

+1

@Ted Hopp s1 == s2 sẽ là true vì * liên tục tổng hợp *. – EJP

Trả lời

14

HashMap so sánh các đối tượng bằng cách gọi equals()hashCode().
String ghi đè các phương pháp này để so sánh theo giá trị.

4

Nếu hai Strings đó đều giống nhau là không thực sự bình đẳng

Nhưng họ. Chúng bằng nhau theo phương thức equals(), và đó là kỹ thuật được chỉ định cho kiểm tra bình đẳng trong giao diện Map.

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

Nhưng nó không sai! Cả hai đều tham chiếu đến cùng một chuỗi vì liên tục tổng hợp bởi trình biên dịch.

2

Khi HashMap so sánh khóa trong nội bộ, nó sử dụng phương thức equals(), không phải ==. Vì vậy, đối tượng bình đẳng là tốt cho một trận đấu quan trọng, bình đẳng tham khảo không cần thiết nếu equals() sẽ bị thay thế (như trong trường hợp của java.lang.String.)

5

Nói chung, bạn có thể sử dụng đối tượng String vì HashMap sử dụng equals() và không == để kiểm tra bình đẳng chính.

1

System.out.println (s1 == s2); // phải là false

Không được. Trình biên dịch Java có thể tối ưu hóa và chỉ hai chuỗi vào cùng một vị trí.

Cập nhật

public class Test { 

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

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

} 

Output

javac Test.java 
java Test 
> true 
+0

Sai, sai, sai. Bạn có thể dễ dàng chứng minh nó bằng mã đơn giản. – duffymo

+3

Không, không sai. Nó được gọi là "interning". –

+2

Bởi "có thể tối ưu hóa" tôi nghĩ rằng bạn có nghĩa là "phải tối ưu hóa", giả sử trình biên dịch Java là lên đến spec. http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5 – yshavit

-2

chúng ta thực sự nên trở về là người đầu tiên cơ bản. khoa học

máy tính cơ bản:

== so sánh địa chỉ bộ nhớ (tham khảo)

Equals so sánh giá trị được lưu trữ trong bộ nhớ địa chỉ

java cơ bản. chỉ có một bản sao của đối tượng chuỗi trên toàn bộ jvm

+3

Hầu hết mọi dòng trong câu trả lời của bạn đều bị mờ hoặc mờ nhạt – SLaks

+0

Đây không phải là 'nguyên tắc cơ bản về khoa học máy tính'. Chúng là các nguyên tắc cơ bản về * Java *. Tham chiếu Java không nhất thiết là địa chỉ bộ nhớ. Có thể có nhiều bản sao của một chuỗi nếu bạn sử dụng cấu trúc 'chuỗi mới (...)'. – EJP

Các vấn đề liên quan