8

でConcurrentDictionaryを並べ替える私はそうのような値で、私のConcurrentDictionaryをソートすることができる午前:私は効果的に辞書を並べ替え、辞書としてその新しい再順序付けられたリストを設定したい除いて、素晴らしいです

static ConcurrentDictionary<string, Proxy> Proxies = 
    new ConcurrentDictionary<string, Proxy>(); 

Proxies.OrderBy(p => p.Value.Speed); 

ソートされたアイテムの結果リストを受け取るのではなく、それ自体です。

私はこのような何かをしようとするが、運がなかった - の後に辞書がまだ順不同である:それはそれを行うように思える

Proxies = new ConcurrentDictionary<string,Proxy>(
    Proxies.OrderBy(p => p.Value.Speed)); 

が辞書には影響しません。私も、OrderByの結果を代理人に影響を与えるかもしれないがまだ運がないと考える新しいvarにキャストしようとしました。

このConcurrentDictionaryを並べ替えると、辞書をOrderByの並べ替えの結果にすることはできますか?

+0

あなたがスレッドの安全性と継続的なソートと組み合わせ辞書の高速アクセスのプロパティを、必要な場合は、あなたのようなものが必要並行Bツリー。私は.NETですぐに利用できるものはないと思います。おそらく第三者ですか?結果が必要なときには、単にOrderBy()を使うことができますか? – Timo

答えて

6

単純な辞書はソートされたコレクションではありません。それらは単にキーを値にマップするコレクションです。 ConcurrentDictionaryも変わりません。

代わりにSortedConcurrentDictionarySortedDictionaryに似ています)が必要ですが、このデータ構造は存在しません。

実際にソートされた「辞書」が必要な場合は、ユースケースについて詳しく聞く必要があります。これは偽優先キューですか?あなたは単にConcurrentBag<Proxy>を使用して事実の後に発注することができますか?

コレクションを取得し、下流の並列方法でプロキシをソート順に使用する場合は、MSDN example of an OrderablePartitionerから借用する可能性があるcustom Partitionerを作成することをお勧めします。

+0

ディクショナリは重複値の追加を防止する目的でのみ使用されていました。以前は、リストを使用していましたが、追加する前に値が存在するかどうかを確認していました。 ConcurrentBag を使用することができますが、リストビュー内のプロキシのアクティブな表示と管理ビューを維持し、プロキシを表示/管理できるようにするためには2つの別個のリストを使用する必要があります。ロック機構を使用したリストの以前の実装は、nullアイテムが存在するバグに近づくまではかなりうまくいっていましたので、ConcurrentBag/Dictionary /などに切り替えることを試みました... – user1111380

+0

これは、 HashSet'は 'ConcurrentBag'が見つからないものです。別のスレッドが来て更新するため、これは同時に起こりますか? – user7116

+0

Rgiht、私はプロキシをチェックし、それに応じてリストを更新するために複数のスレッドを使用しています。 – user1111380

0

ConcurrentDictionaryは、ちょうどDictionaryのように、ソートの概念を知らない、つまり順序​​情報を含まない。 OrderBy()の結果には特定の順序がありますが、Proxiesに代入すると注文情報が失われます。

IDictionaryのソートされた実装、つまりSortedDictionarySortedListがあることに注意してください。

+0

これはBCLチームが調べることができる問題ですか? – Eniola

2

辞書、特にConcurrentDictionaryは基本的にソートされていません。

ソートされたコレクションが必要な場合は、値をSortedDictionary<T,U>などの別のタイプで保存する必要があります。

+0

私は、ConcurrentDictionaryが提供する組み込みの.NET並行性を利用することを望んでいました。ソートされた機能を提供している間、これは不可能であることがわかります。 lock()ステートメントの使用に戻る...ありがとう。 – user1111380

+1

@ user1111380ちょっと注意してください - 並び替えと並行収集は通常競合します...通常は(可能な場合)、データを作業中に並行コレクションに保持し、特定の順序でアイテムを抽出して結果を提示することをお勧めしますなど。 –

+0

コレクションの作業が書き込み集中型よりも読み込み集中型である特定の順序でアイテムを取得することは、かなり高価になる可能性があります。 ConcurrentDictionaryを更新し、アイテムのソートがアトミックにアップデートの一部になるようにするケースがあります。辞書全体を必要なソート順序で再初期化する必要はありません。 そのためには、ConcurrentSortedDictionaryまたはSortedConcurrentDictionaryはBCLに持つのがいいでしょう。 – Eniola

2

解決策は、多くの研究とコード改訂の後に発見されたSortedSet<T>を使用することです。ソートされたセットは、DictionaryまたはHashSetのユニークさを提供しますが、並べ替えも可能です。DictionaryHashSetも並べ替えができません。

+2

SortedSetがConcurrentでないことを除きますか?並び替えをサポートするコレクションを持っていると私たちのツールバッグには欠かせないアイテムです。私は、BCLチームにこれを見てもらうよう勧めなければならないと思います。 – Eniola

1

たぶんない効率的なあなたは不変クラスで、多くの場合、それを呼び出す、単純な場合:

Imports System.Collections.Concurrent 

Public Class SortedConcurrentDictionary(Of TKey, Tvalue) 
Inherits ConcurrentDictionary(Of TKey, Tvalue) 

    Shadows ReadOnly Property Values As IEnumerable(Of Tvalue) 
     Get 
      If MyBase.Values.Count = 0 Then 
       Return MyBase.Values 
      End If 
      Return From k In Keys Order By k Select Me(k) 
     End Get 
    End Property 
End Class 
+0

興味深いアイデアだが、これはどのようにパフォーマンスが良いのだろうか?内容の列挙ごとにキーがソートされているようですね。 – Eniola

+0

@エニオラあなたは大丈夫です、私が言ったように、「おそらく効率的でないかもしれない」。より洗練されたバージョンは、ディシジョンが変更されたときにキャッシュをキャッシュし、リフレッシュします。 – smirkingman