20

Java Docsによると、putIfAbsentこれは

   if (!map.containsKey(key)) 
      return map.put(key, value);
   else
      return map.get(key);

したがって、キーがマップに存在する場合、その値は更新されません。これは正しいです?

いくつかの基準に基づいてキー値を更新したい場合はどうなりますか?有効期限などを言います。

これは、キャッシュを追加および更新するためのより良い実装でしょうか?

public void AddToCache(T key, V value)
{
   V local = _cache.putifabsent(key, value);

   if(local.equals(value) && local.IsExpired() == false){
     return;
   }
   // this is for updating the cache with a new value
   _cache.put(key, value);
}
4

2 に答える 2

13

したがって、キーの値は更新されません。これは正しいです?

それは正しいです。すでにマップにあった現在の値を返します。

これは、キャッシュを追加および更新するためのより良い実装でしょうか?

いくつかのことがあなたの実装をより良くするでしょう。

1. putIfAbsentを使用して存在するかどうかをテストするのではなく、存在しないかどうかを確認する場合にのみ使用してくださいputIfAbsent。代わりに、そのmap.get存在(またはmap.contains)をテストするために使用する必要があります。

    V local = _cache.get(key);
    if (local.equals(value) && !local.IsExpired()) {
        return;
    }

2.置く代わりに、置き換えたいと思うでしょう。これはif、2つ(またはそれ以上)のスレッドの1つが他のスレッドのプットを上書きする2つ以上のスレッドによって、がfalseと評価される競合状態が発生する可能性があるためです。

代わりにできることは、置き換えることです

すべてが言われ、行われるとき、それはこのように見えるかもしれません

public void AddToCache(T key, V value) {
    for (;;) {

        V local = _cache.get(key);
        if(local == null){
            local = _cache.putIfAbsent(key, value);
            if(local == null)
                return;
        }
        if (local.equals(value) && !local.IsExpired()) {
            return;
        }

        if (_cache.replace(key, local, value))
            return;
    }
}
于 2012-05-07T17:40:02.387 に答える
4

キーが以前にマップになかった場合、コードはNPEをスローします。

それ以外は、これは合理的なアイデアですが、「並行」環境では機能しません。このputIfAbsent()メソッドが追加された理由は、マップが操作をスレッドセーフにするために使用している基本的なサポートを使用して、操作のアトミック性を管理できるようにするためです。あなたの実装では、2人の異なる呼び出し元がお互いのステップを終了する可能性があります(最初の呼び出し元は期限切れの値を新しい値に置き換え、2番目の呼び出し元はすぐに最初の新しい値を2番目の新しい値に置き換えます)。

于 2012-05-07T17:39:43.187 に答える