7

不変の Token オブジェクトのリストで構成される TokenList という不変のクラスがあります。これも不変です。

@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;
    }
}

これらの TokenList に対して、複数の TokenList を入力として取り、単一の TokenList を出力として返す操作をいくつか実行します。任意の数の TokenList が入る可能性があり、それぞれが任意の数の 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 があり、アプリケーション内でアクティブな TokenList オブジェクトが常に最大で約 1,000,000 あると考えています。これと、UUID がキャッシュ キーで組み合わせて使用​​されるという事実を考えると、これが間違った結果を生み出す可能性はほとんどないように思われます。とはいえ、「汚い」と感じるだけで先に進むのは不安です。このシステムを使用してはいけない理由はありますか? UUID.randomUUID() によって使用される SecureRandom のパフォーマンス コストは、利益を上回りますか (特に、複数のスレッドが同時にこれを実行すると予想されるため)。衝突は私が思っているよりも起こりそうですか? 基本的に、このようにすると何か問題がありますか??

ありがとう。

4

2 に答える 2

3

あなたがしようとしていることは非常にトリッキーで、詳細な分析が必要です。したがって、アプローチを決定する前に、以下の質問を確認する必要があります。

これらの操作はコストが高く、同じ操作 (つまり、同じ入力) が複数回実行される可能性が高くなります。

1) 上記の行で「同じ入力」と言うとき、正確には何を意味しますか? これは、まったく同じオブジェクト、つまり、複数の参照 (同じメモリ位置) を介して参照される 1 つのオブジェクトを意味するのでしょうか、それとも、メモリに関して個別のオブジェクトであるが、論理的には同じデータを持つことを意味するのでしょうか??

ここで、オブジェクトが同じ、つまり同じメモリ位置である場合、== 比較はうまくいきます。このためには、オブジェクト参照をキーとしてキャッシュに保持する必要があります。

しかし、それが 2 番目のケース、つまりメモリに関しては別々のオブジェクトであるが論理的には同じである場合、UUID は役に立たないと思います。そのような 2 つの別個のオブジェクトが同じ UUID を取得することを確認する必要があるためです。とにかく、これを確認するために TokenList データ全体を調べなければならないので、これはそれほど簡単ではありません

2) キャッシュでハッシュコードを使用するのは安全ですか? 2 つのオブジェクトが異なっていても、同じハッシュコードを持つ可能性があるため、ハッシュコードをキーとして使用しないことをお勧めします。したがって、あなたの論理はひどく間違っているかもしれません。

したがって、まずこれらの質問に対する答えを明確にしてから、アプローチについて考えてください。

于 2012-11-15T11:28:46.360 に答える
0

SecureRandomブーストはありません。通常よりも「より」ランダムですRandom。衝突の可能性は、数の 2 乗を可能な UUID の合計で割った程度なので、非常に小さい数です。それでも、番号が常に一意であるとは限りません。これを試すこともできますが、番号がハッシュコード リストの他の場所にまだ含まれていないことを確認することをお勧めします。そうしないと、非常に奇妙な問題が発生する可能性があります...

于 2012-11-15T11:23:55.553 に答える