我有一个不可变的类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作为输出。可以有任意数量的TokenLists进入,每个TokenLists可以有任意多个Tokens。
这些操作很昂贵,并且很有可能多次执行相同的操作(即相同的输入),所以我想缓存输出。但是,性能至关重要,我担心在这些可能包含任意多个元素的对象上执行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的性能成本是否会超过收益(特别是因为我希望多个线程同时执行此操作)?碰撞是否比我想象的更可能?基本上,这样做有什么不妥吗?
感谢。
答案 0 :(得分:3)
你正在尝试的是非常棘手的,需要详细的分析。因此,在决定任何方法之前,您需要检查以下问题。
这些操作很昂贵,并且很有可能多次执行相同的操作(即相同的输入)
1)当您在上面的行中说“相同输入”时,您的意思是什么?这是否意味着,完全相同的对象,即通过多个引用(相同的内存位置)引用的一个对象,或者它是指内存方式分离的对象,但逻辑上具有相同的数据?
这里如果对象是相同的,即相同的内存位置,那么==比较就可以了。为此,您必须将对象引用保留为缓存中的键。
但是,如果它是第二种情况,即内存方式分离的对象,但在逻辑上相同,那么我认为UUID不会帮助你。因为您必须确保这两个单独的对象将获得相同的UUID。这不会太容易,因为无论如何你必须通过整个TokenList数据来确保这个
2)在缓存中使用哈希码,是否安全?我建议不要使用hashcode作为密钥,因为即使2个对象不同,它们也可能具有相同的哈希码。所以你的逻辑可能会非常错误。
因此,首先要清楚地了解这些问题的答案。然后才考虑方法。
答案 1 :(得分:0)
SecureRandom
不会给你任何提升,它比普通Random
“更”随机。碰撞的可能性是数字平方除以总可能的UUID的顺序,因此数量非常小。不过,我不会依赖这个数字总是独一无二的。您可以尝试这样做,但最好检查并确保该数字尚未包含在哈希码列表中的其他位置。否则,你可能会遇到一些非常奇怪的问题......