簡體   English   中英

使用UUID進行廉價的equals()和hashCode()

[英]Using UUIDs for cheap equals() and hashCode()

我有一個不可變的類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的性能成本是否會超過收益(特別是因為我希望多個線程同時執行此操作)? 碰撞是否比我想象的更可能? 基本上,這樣做有什么不妥嗎?

謝謝。

你正在嘗試的是非常棘手的,需要詳細的分析。 因此,在決定采用任何方法之前,您需要檢查以下問題。

這些操作很昂貴,並且很有可能多次執行相同的操作(即相同的輸入)

1)當您在上面的行中說“相同輸入”時,您的意思是什么? 這是否意味着,完全相同的對象,即通過多個引用(相同的內存位置)引用的一個對象,或者它是指內存方式分離的對象,但邏輯上具有相同的數據?

這里如果對象是相同的,即相同的內存位置,那么==比較就可以了。 為此,您必須將對象引用保留為緩存中的鍵。

但如果它是第二種情況,即內存方式單獨的對象,但在邏輯上相同,那么我不認為UUID會幫助你。 因為您必須確保這兩個單獨的對象將獲得相同的UUID。 這將是不容易的,因為無論如何你必須通過整個TokenList數據來確保這一點

2)在緩存中使用哈希碼,是否安全? 我建議不要使用hashcode作為密鑰,因為即使2個對象不同,它們也可能具有相同的哈希碼。 所以你的邏輯可能會出錯。

因此,首先要明確這些問題的答案,然后才考慮方法。

SecureRandom不會給你任何提升,它比普通Random “更”隨機。 碰撞的可能性是數字平方除以總可能的UUID的順序,因此數量非常小。 不過,我不會依賴這個數字總是獨一無二的。 您可以嘗試這樣做,但最好檢查並確保該數字尚未包含在哈希碼列表中的其他位置。 否則,你可能會遇到一些非常奇怪的問題......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM