2012-04-26 5 views
1

私は面白い問題があります。私はいくつかの助けが必要です。私はFIFOと他の自然順序のキー(ConcurrentMap)に基づいた2つの別々の条件の2つのキューを実装しました。つまり、両方のキューに同じデータが異なる順序で配置されたイメージを作成できます。いくつかの基準に基づいてConcurrentMapのキーを見つけると、FIFOマップ内のキーの「位置」を見つける最良の方法は何か、私が持っている質問(そしてこれを行う効率的な方法を探しています)です。本質的に私はそれが最初のキー(これは簡単です)か、それとも10番目のキーかを知りたいと思います。Java ConcurrentMap - マップ内のキーの位置

ご協力いただければ幸いです。

+0

正確な位置、または近似値が欲しいですか?また、同じデータ/キーを再度挿入しますか? –

+0

もう少し考えれば、近似は実際は大丈夫でしょう。何かご意見は?いいえ、同じキーを再度挿入する必要はありません。 –

+0

@Alan基本構造が検索ツリーまたはスキップリストのバリエーションである場合、深さ制限検索。 – trutheality

答えて

0

私は以下のコードのようなものが仕事をすると信じています。抽象メソッドとしてelement - > keyの実装を残しました。カウンタが増加する数を要素に割り当てるために使用されていることに注意してください。また、add(...)が複数のスレッドによって呼び出されている場合、FIFO内の要素は緩やかに順序付けされるだけであることにも注意してください。それは豪華なmax(...)min(...)ロジックを強制します。またその理由は、およそです。最初と最後は特殊なケースです。最初に明確に示すことができます。現在の実装が実際のインデックスを返すため、最後は扱いにくいです。

これはおおよその場所なので、0.01.0の間のAPIをfloatに戻して、キュー内の相対位置を示すことを検討することをおすすめします。あなたのコードがpop(...)以外のいくつかの手段を用いて除去することをサポートする必要がある場合

、あなたはすべての適切なint/floatキャスト&丸めて、おおよそのサイズを使用し、((id - min)/(max - min)) * sizeへの復帰を変更する必要があります。

public abstract class ApproximateLocation<K extends Comparable<K>, T> { 

    protected abstract K orderingKey(T element); 

    private final ConcurrentMap<K, Wrapper<T>> _map = new ConcurrentSkipListMap<K, Wrapper<T>>(); 
    private final Deque<Wrapper<T>> _fifo = new LinkedBlockingDeque<Wrapper<T>>(); 
    private final AtomicInteger _counter = new AtomicInteger(); 

    public void add(T element) { 
     K key = orderingKey(element); 
     Wrapper<T> wrapper = new Wrapper<T>(_counter.getAndIncrement(), element); 
     _fifo.add(wrapper); 
     _map.put(key, wrapper); 
    } 

    public T pop() { 
     Wrapper<T> wrapper = _fifo.pop(); 
     _map.remove(orderingKey(wrapper.value)); 
     return wrapper.value; 
    } 

    public int approximateLocation(T element) { 
     Wrapper<T> wrapper = _map.get(orderingKey(element)); 
     Wrapper<T> first = _fifo.peekFirst(); 
     Wrapper<T> last = _fifo.peekLast(); 
     if (wrapper == null || first == null || last == null) { 
      // element is not in composite structure; fifo has not been written to yet because of concurrency 
      return -1; 
     } 
     int min = Math.min(wrapper.id, Math.min(first.id, last.id)); 
     int max = Math.max(wrapper.id, Math.max(first.id, last.id)); 
     if (wrapper == first || max == min) { 
      return 0; 
     } 
     if (wrapper == last) { 
      return max - min; 
     } 
     return wrapper.id - min; 
    } 

    private static class Wrapper<T> { 
     final int id; 
     final T value; 

     Wrapper(int id, T value) { 
      this.id = id; 
      this.value = value; 
     } 
    } 
} 
+0

非常にDilum、ありがとう、これは非常にきちんとしたコードです。私は現時点でそれを評価しています - 概算が大丈夫な理由は、FIFO位置を重み関数として使用してキューの停滞を検出しようとしていることです。 –

+0

ちょうどDilumをフォローアップしています。これは現在、私がしたいことをうまくやっています。再度、感謝します –

1

FIFOマップの順序にアクセスするためのAPIはありません。あなたができる唯一の方法は、keySet()values()またはentrySet()以上の繰り返しです。

+0

ありがとうございました - 私はこれが事件であったかもしれないと心配しました。 –

+0

+1ポジションはいつでも変更できます。位置がどこであったか、移動したか、削除されたかを判断するまでには、反復処理中に削除することもできます。あなたはその注文をせいぜい重要ではなく、信頼できないものとして扱うべきです。 –

0

ConcurrentNavigableMapを使用できる場合、headMapのサイズは、まさにあなたが望むものを提供します。

+0

私はそれがうまくいくかどうかはわかりませんが、Key Ordered Mapのポジションは私に与えられますが、FIFOにインデックスを付けるのでしょうか? –

+0

このインタフェースを実装するFIFO実装がある場合は、標準ライブラリにはありません。 – trutheality

関連する問題