我有一个不可变类 TokenList,它由一个 Token 对象列表组成,这些对象也是不可变的:
@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;
}
}
我对这些 TokenLists 做了几个操作,它们将多个 TokenLists 作为输入并返回一个 TokenList 作为输出。可以有任意多个 TokenList 进入,每个 Token 可以有任意多个 Token。
这些操作很昂贵,并且很有可能多次执行相同的操作(即相同的输入),所以我想缓存输出。但是,性能至关重要,我担心在这些可能包含任意多个元素的对象上执行 hashCode() 和 equals() 的费用(因为它们是不可变的,所以可以缓存 hashCode,但 equals 仍然很昂贵)。
这让我想知道是否可以通过对 TokenList 进行以下更新来简单而廉价地使用 UUID 提供 equals() 和 hashCode():
@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;
}
}
像这样作为缓存键的东西:
@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;
}
}
我认为有 2^128 个不同的 UUID,我可能随时在应用程序中最多有大约 1,000,000 个处于活动状态的 TokenList 对象。鉴于此,以及 UUID 在缓存键中组合使用的事实,似乎产生错误结果的可能性非常小。然而,我对继续它感到不安,因为它只是感觉“肮脏”。有什么理由我不应该使用这个系统吗?UUID.randomUUID() 使用的 SecureRandom 的性能成本是否会超过收益(特别是因为我希望多个线程同时执行此操作)?碰撞会比我想象的更有可能吗?基本上,这样做有什么问题吗?
谢谢。