J'ai besoin d'un type de données capable d'insérer des entrées et de déterminer rapidement si une entrée a déjà été insérée. Un Dictionary
semble répondre à ce besoin (voir exemple). Cependant, je n'ai aucune utilité pour le values
du dictionnaire. Dois-je toujours utiliser un dictionnaire ou existe-t-il un autre type de données mieux adapté?
public class Foo
{
private Dictionary<string, bool> Entities;
...
public void AddEntity(string bar)
{
if (!Entities.ContainsKey(bar))
{
// bool value true here has no use and is just a placeholder
Entities.Add(bar, true);
}
}
public string[] GetEntities()
{
return Entities.Keys.ToArray();
}
}
Vous pouvez utiliser HashSet<T>
.
Le
HashSet<T>
La classe fournit des opérations d'ensemble hautes performances. Un ensemble est une collection qui ne contient aucun élément en double et dont les éléments ne sont pas dans un ordre particulier .
réponse d'Habib est excellent, mais pour les environnements multi-threads si vous utilisez un HashSet<T>
alors, par conséquent, vous devez utiliser lock
s pour en protéger l'accès. Je me trouve plus enclin à créer des blocages avec des instructions lock
. De plus, lock
s produit une accélération moins bonne par loi d'Amdahl car l'ajout d'une instruction lock
réduit le pourcentage de votre code qui est réellement parallèle.
Pour ces raisons, un ConcurrentDictionary<T,object>
correspond à la facture dans les environnements multi-thread. Si vous finissez par en utiliser un, enveloppez-le comme vous l'avez fait dans votre question. Juste new
up object
s pour ajouter autant de valeurs que nécessaire, car les valeurs ne seront pas importantes. Vous pouvez vérifier qu'il n'y a pas d'instructions .lock
dans son code source
Si vous n'aviez pas besoin de mutabilité de la collection, ce serait théorique. Mais votre question implique que vous en avez besoin, car vous avez une méthode AddEntity
.
Informations supplémentaires 2017-05-19 - en fait, ConcurrentDictionary
le fait utilise des verrous en interne, mais pas lock
instructions en soi - il utilise Monitor.Enter
(découvrez la méthode TryAddInternal
). Cependant, il semble verrouiller des compartiments individuels dans le dictionnaire, ce qui signifie qu'il y aura moins de conflits que de placer le tout dans une instruction lock
.
Donc, dans l'ensemble, ConcurrentDictionary
est souvent meilleur pour les environnements multithread.
Il est en fait assez difficile (impossible?) De créer un ensemble de hachage simultané en utilisant uniquement les méthodes Interlocked . J'ai essayé par moi-même et j'ai continué à rencontrer le problème de devoir modifier deux choses en même temps - quelque chose que seul le verrouillage peut faire en général. Une solution de contournement que j'ai trouvée consistait à utiliser des listes à liaison unique pour les compartiments de hachage et à créer intentionnellement des cycles dans une liste lorsqu'un thread devait fonctionner sur un nœud sans interférence d'autres threads; cela entraînerait d'autres threads à se coincer en tournant au même endroit jusqu'à ce que ce thread soit fait avec son nœud et annule le cycle. Bien sûr, techniquement, il n'utilisait pas de verrous, mais il ne s'est pas bien adapté.