2012-03-08 24 views
9

Todavía soy bastante nuevo en C#, pero noté las ventajas de las publicaciones en el foro de usar un HashSet en lugar de un List en casos específicos.¿Cuál es el método más rápido/más seguro para iterar sobre un HashSet?

Mi caso actual no es que estoy almacenando una gran cantidad de datos en un único List, pero en lugar de tener que verificar miembros a menudo.

El problema es que, de hecho, también necesito iterar sobre él, pero el orden en que se almacenan o recuperan realmente no importa.

He leído que para cada uno de los bucles es más lento que para el siguiente, entonces, ¿de qué otro modo podría hacerlo en el método más rápido posible?

El número de comprobaciones de .Contains() que estoy haciendo definitivamente está perjudicando mi rendimiento con las listas, por lo que al menos en comparación con el rendimiento de HashSet sería útil.

Editar: Actualmente estoy usando listas, iterando a través de ellas en numerosas ubicaciones, y se está ejecutando código diferente en cada ubicación. En la mayoría de los casos, las listas actuales contienen coordenadas de punto que luego uso para referirme a una matriz bidimensional para que luego haga una operación u otra según los criterios de la lista.

Si no hay una respuesta directa a mi pregunta, está bien, pero supuse que podría haber otros métodos de iteración en un ciclo HashSet que solo foreach. Actualmente estoy en la oscuridad en cuanto a qué otros métodos podría haber, qué ventajas ofrecen, etc. Suponiendo que hay otros métodos, también asumí que habría un método de elección preferido típico que solo se ignora cuando no satisface las necesidades (mis necesidades son bastante básicas).

Por lo que respecta a la optimización prematura, ya sé que usar las listas como lo que soy es un cuello de botella. Cómo ayudar a este problema es donde me estoy estancando. Ni siquiera me pegué exactamente, pero no quería volver a inventar la rueda probando repetidamente solo para descubrir que ya lo estoy haciendo de la mejor manera posible (este es un gran proyecto con más de 3 meses invertidos, las listas están en todas partes) , pero definitivamente hay unos que no quiero duplicados, tengo una gran cantidad de datos, no necesito almacenarlos en ningún orden específico, etc.).

+1

¿Qué estás planeando hacer en la iteración? Ejecutar código? ¿Cuenta algo? –

+3

Está optimizando prematuramente. Ahora eso no quiere decir que usted debe ignorar las implicaciones de rendimiento de sus estructuras de datos y el código completo, pero si necesita la semántica de un HashSet continuación, el siguiente paso es que el perfil de la iteración en el contexto de su programa y la forma en que normalmente habrá correr. Si la iteración no es un cuello de botella de rendimiento, entonces continúa, no vale la pena el tiempo. No supongas que será, prueba. –

+1

No sé nada acerca de la respuesta, pero mi convención dice que el método más rápido no será el más seguro y el más seguro suele ser el más rápido. Creo que si un método es el más rápido y el más seguro, entonces no debe haber otros métodos. Puedo estar equivocado. – nawfal

Respuesta

8

Un bucle foreach tiene una pequeña cantidad de sobrecarga adicional en una colección indexada (como una matriz). Esto se debe principalmente a que foreach hace un poco más de comprobación de límites que un bucle for.

HashSet no tiene un indexador, por lo que debe usar el enumerador.

En este caso foreach es eficiente ya que solo llama a MoveNext() a medida que se mueve a través de la colección.

También Parallel.ForEach puede mejorar drásticamente su rendimiento, según el trabajo que esté realizando en el ciclo y el tamaño de su HashSet.

Como se mencionó anteriormente, la creación de perfiles es su mejor opción.

4

No debe iterar sobre un hashset en primer lugar para determinar si hay un elemento en él. Debe usar el método HashSet (no el LINQ). El HashSet está diseñado de tal manera que no necesitará examinar todos los elementos para ver si un valor dado está dentro del conjunto. Eso es lo que lo hace tan poderoso para buscar en una lista.

+6

Él dice en su pregunta que necesita poder buscar e iterar, no iterar para buscar. – JamieSee

2

No es estrictamente responder a la pregunta en la cabecera, pero más con respecto a su problema específico:

me gustaría hacer su propio Collection objeto que utiliza tanto un HashSet y una List internamente. La iteración es rápida, ya que puede usar la Lista; la comprobación de Contains es rápida, ya que puede usar el HashSet. Justo lo convierten en un IEnumerable y se puede utilizar esta colección en foreach también.

La desventaja es más memoria, pero sólo hay dos veces tantas referencias al objeto, no el doble de objetos. En el peor de los casos, es solo el doble de memoria, pero pareces mucho más preocupado por el rendimiento.

Agregar, verificar e iterar son rápidos de esta manera, solo la eliminación sigue siendo O (N) debido a List.

EDITAR: Si la eliminación también debe ser O (1), conviértalo en una lista de doble puntero y convierta el HashSet en un diccionario para que pueda encontrar rápidamente la ubicación del objeto en la lista.

0

que tenían el mismo problema, donde el HashSet se adapte muy bien la adición de elementos únicos, pero es muy lento al conseguir elementos en un bucle. Lo resolví convirtiendo el HashSet en una matriz y luego ejecuté el sobre.

Cuestiones relacionadas