2012-02-24 33 views
5

Tại sao có giá trị hashCode khác nhau cho mỗi lần bạn chạy chính java? Xem mã ví dụ bên dưới.Tạo Enum HashCode khác nhau?

interface testInt{ 

    public int getValue(); 
} 

enum test implements testInt{ 
    A(1), 
    B(2); 

    private int value; 

    private test(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return this.value; 
    } 
} 

Đối với mỗi khi bạn chạy,

public static void main(String[] args) { 
    System.out.println(test.A.hashCode()); 
} 

sẽ có giá trị in khác nhau trên console. Tại sao không nhất quán?

Trả lời

3

Nếu bạn muốn cùng một giá trị mỗi lần, hãy sử dụng .ordinal() hoặc thậm chí tốt hơn, sử dụng getValue() như bạn có. Bạn có thể ghi đè hashCode() từ giá trị mặc định để cung cấp cho nó một số dựa trên cách đối tượng được tạo.

+0

Vâng, hiện tại tôi đang sử dụng getValue như một giải pháp. Chỉ cần tạo bài đăng để xem lý do tại sao các mã băm khác nhau khi triển khai giao diện. Cảm ơn. –

2

Các javadocs nêu rõ điều đó. Từ javadocs cho phương thức mã băm trong Object c lớp

Thực tế là phương pháp hashCode được xác định bởi lớp Object trả về các số nguyên riêng biệt cho các đối tượng riêng biệt. (Điều này thường được thực hiện bằng cách chuyển đổi địa chỉ nội bộ của đối tượng thành một số nguyên, nhưng kỹ thuật triển khai này không được yêu cầu bởi ngôn ngữ lập trình JavaTM.)

Vì vậy, trên các mã demo khác nhau, địa chỉ nội bộ có thể thay đổi và do đó nó là hoàn toàn bình thường để bạn có thể thấy các giá trị khác nhau.

Tùy thuộc vào nhu cầu của bạn, nếu bạn muốn phương thức hashcode() trả về cùng giá trị trên các lời mời jvm, bạn nên ghi đè phương thức để trả về giá trị tùy chỉnh. Tuy nhiên, bạn nên biết điều này có thể là thảm họa nếu đối tượng được sử dụng trong các bộ sưu tập dựa trên băm (tăng cơ hội va chạm băm).

+0

Như tôi đã nói. Điều mang tôi đến đây là sự thật, các enums đơn giản, trong Oracle JVM7 của tôi, đã trả về cùng một hashCode trên các lần chạy khác nhau. Nhưng khi trao đổi với enum chuyên biệt, hashcode là khác nhau cho mỗi lần chạy. –

3

"Không có yêu cầu giá trị băm nhất quán giữa các triển khai Java khác nhau hoặc thậm chí giữa các lần chạy thực thi khác nhau của cùng một chương trình."

http://en.wikipedia.org/wiki/Java_hashCode%28%29

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#hashCode%28%29

public static void main(String[] args) { 
    System.out.println(test.A.hashCode()); 
    System.out.println(test.A.hashCode()); 
} 

Mã này bây giờ sẽ tạo ra cùng hashCode.

+0

Ok, nhưng, điều đó chỉ xảy ra nếu bạn có một enum thực hiện một giao diện. –

+0

Không nhất thiết. Nếu bạn đang so sánh để sản xuất hashcode của một chuỗi (hoặc một cái gì đó khác) giữa thực hiện chương trình, thực tế là họ tạo ra cùng một mã có thể là một trùng hợp ngẫu nhiên. – jn1kk

+0

Tôi đoán trùng hợp ngẫu nhiên không phải là từ thích hợp ở đây. Nó thực sự trả về cùng một giá trị hashCode cho các enums không thực hiện bất kỳ giao diện nào. Đó là điều đã chỉ cho tôi ở đây. –

0

Có thể một số triển khai JVM về cơ bản sẽ trả về Enum.ordinal() (cũng sẽ làm cho số lượng lớn hashCode) - nhưng nó sẽ không thay đổi bất kỳ điều gì. Giá trị hashCode() không nhất quán giữa các lần thực hiện hoặc các JVM. Hợp đồng yêu cầu duy nhất được mô tả trong JavaDocs của Object.hashCode() - và nó là việc thực hiện trong Object được sử dụng trong enum.

Cũng lưu ý rằng thực hiện một giao diện không có gì để làm với hashCode():

public class TestEnum { 

    public static void main(String[] args) { 
     System.out.println(Silly.B.hashCode()); 
     System.out.println(Silly.C.hashCode()); 
     System.out.println(Silly.D.hashCode()); 
    } 
} 

enum Silly { 
    B, C, D 
} 

Chương trình này cũng trả về khác nhau hashCode() s trên mỗi chạy.

+0

Ok, Silly.B.hashCode, sẽ trả về cùng một hasCodes và không khác nhau. Nếu thực hiện một giao diện không có gì để làm với hashCode, tại sao điều đó xảy ra? Bạn có thấy nơi tôi đến không? Silly.B.hashCode bằng với các lần chạy khác nhau, nhưng nếu bạn tạo Silly thực hiện một giao diện đơn giản, thì sẽ có các mã băm khác nhau cho Silly.A –

+0

@ VíctorHugo: JVM nào bạn đang sử dụng? Trên 1.6.0_26-b03 đôi khi nó trả về giá trị giống nhau và đôi khi khác nhau, nhưng chắc chắn chúng không giống nhau ... –

+0

JVM, jdk1.7.0_02 (Oracle) –

0

Enum.hashCode không được xác định để trả về bất kỳ giá trị cụ thể nào (trừ tuân thủ các quy tắc của Object.hashCode) và triển khai phổ biến không làm bất kỳ điều gì đặc biệt.

Tại sao? Nếu bạn đang sử dụng các enums (chỉ) trong một HashSet hoặc như là một chìa khóa trong một HashMap, tốt, bạn nên sử dụng tối ưu hóa EnumSet hoặc EnumMap. Bây giờ hãy xem xét nếu enum được sử dụng cùng với các loại khác trong một HashSet. Có lẽ bạn có một số "tùy chọn tiêu chuẩn" để triển khai giao diện, nhưng những người khác có thể đi kèm với các tùy chọn của riêng họ. Bất cứ điều gì không quốc tịch sẽ làm. Nhiều loại enum trong một HashSet. Nếu Enum đã sử dụng số thứ tự cho giá trị băm, thì bạn sẽ có những va chạm thông thường. Sử dụng System.identityHashCode làm giảm va chạm một cách mạnh mẽ.

public interface Option { 
} 
public enum StandardOptions implements Option { 
    A, B, C 
} 
enum CustomOptions { 
    P, Q, R 
} 
enum MoreOptions { 
    X, Y, Z 
} 

    Set<Option> options = new HashSet<>(); 
    options.add(A); 
    options.add(P); 
    options.add(X); 

Chúng tôi thực sự không muốn A.hashCode() == P.hashCode() == X.hashCode().

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