Tôi có một lớp học bất biến, TokenList, trong đó bao gồm một danh sách các đối tượng Token, mà cũng là không thay đổi:Sử dụng UUIDs cho equals rẻ() và hashCode()
@Immutable
public final class TokenList {
private final List<Token> tokens;
public TokenList(List<Token> tokens) {
this.tokens = Collections.unmodifiableList(new ArrayList(tokens));
}
public List<Token> getTokens() {
return tokens;
}
}
tôi làm một vài hoạt động bằng các TokenLists lấy nhiều TokenLists làm đầu vào và trả về một TokenList là đầu ra. Có thể có nhiều TokenLists tùy ý đi vào, và mỗi người có thể có nhiều Tokens tùy ý.
Các hoạt động này rất tốn kém và có khả năng hoạt động tương tự (tức là các đầu vào tương tự) sẽ được thực hiện nhiều lần, vì vậy tôi muốn lưu các kết quả đầu ra. Tuy nhiên, hiệu suất là rất quan trọng và tôi lo lắng về chi phí thực hiện hashCode() và equals() trên các đối tượng này có thể chứa nhiều phần tử tùy ý (vì chúng không thay đổi, hashCode có thể được lưu trữ, nhưng bằng vẫn sẽ đắt).
này dẫn tôi đến tự hỏi liệu tôi có thể sử dụng một UUID để cung cấp equals() và hashCode() đơn giản và rẻ tiền bằng cách làm cho các bản cập nhật sau để TokenList:
@Immutable
public final class TokenList {
private final List<Token> tokens;
private final UUID uuid;
public TokenList(List<Token> tokens) {
this.tokens = Collections.unmodifiableList(new ArrayList(tokens));
this.uuid = UUID.randomUUID();
}
public List<Token> getTokens() {
return tokens;
}
public UUID getUuid() {
return uuid;
}
}
Và một cái gì đó như thế này để hoạt động như một khóa bộ nhớ cache:
@Immutable
public final class TopicListCacheKey {
private final UUID[] uuids;
public TopicListCacheKey(TopicList... topicLists) {
uuids = new UUID[topicLists.length];
for (int i = 0; i < uuids.length; i++) {
uuids[i] = topicLists[i].getUuid();
}
}
@Override
public int hashCode() {
return Arrays.hashCode(uuids);
}
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other instanceof TopicListCacheKey)
return Arrays.equals(uuids, ((TopicListCacheKey) other).uuids);
return false;
}
}
Tôi cho rằng có 2^UUID khác nhau và tôi có thể có tối đa 1.000.000 đối tượng TokenList hoạt động trong ứng dụng bất kỳ lúc nào. Với điều này, và thực tế là các UUID được sử dụng kết hợp trong các khóa bộ nhớ cache, có vẻ như là cơ hội của việc tạo ra kết quả sai này biến mất nhỏ. Tuy nhiên, tôi cảm thấy khó chịu về việc tiếp tục với nó vì nó chỉ cảm thấy 'bẩn thỉu'. Có bất kỳ lý do gì mà tôi không nên sử dụng hệ thống này không? Chi phí hiệu năng của SecureRandom được sử dụng bởi UUID.randomUUID() có lớn hơn mức tăng (đặc biệt là vì tôi mong đợi nhiều luồng sẽ làm điều này cùng một lúc)? Các vụ va chạm có nhiều khả năng hơn tôi nghĩ không? Về cơ bản, có điều gì sai trái khi làm theo cách này không ??
Cảm ơn.
Tại sao bạn thực hiện bằng ở vị trí đầu tiên? Nếu bạn không cần nó (và cố gắng thay thế nó bằng UUID thì bạn không nên), đừng ghi đè bằng/hashcode. Nếu bạn muốn nó, bạn cần phải chắc chắn rằng cùng một danh sách mã thông báo bản đồ để cùng một uuid mỗi lần. –
Thực hiện việc này có thể phá vỡ hợp đồng chung trên ['List.equals()'] (http://docs.oracle.com/javase/7/docs/api/java/util/List.html#equals (java.lang) .Object)), đó là những gì bạn muốn? Ngoài ra nếu bằng là đắt tiền, sử dụng 'hashCode' đầu tiên trong bằng, và sau đó chuyển sang bằng thực tế nếu chúng giống nhau. –