2010-04-15 25 views
5

Tengo un objeto java.util.ArrayList<Item> y Item.Cuente las ocurrencias de elementos en ArrayList

Ahora, quiero obtener el número de veces que el Item se almacena en el arraylist.

Sé que puedo hacer arrayList.contains() comprobar pero se cumple, independientemente de si contiene uno o más Item s.

Q1. ¿Cómo puedo encontrar la cantidad de tiempo que el artículo está almacenado en la lista?

Q2. Además, si la lista contiene más de un artículo, ¿cómo puedo determinar el índice de otros artículos porque arrayList.indexOf(item) devuelve el índice del primer artículo cada vez?

+0

citado deroga artículo es igual y el código hash? Necesitan para. –

+0

¿Por qué no extiende la clase ArrayList para agregar la funcionalidad adicional que necesita? Esta es la razón por la que OOP existe;) Q1 se puede hacer fácilmente implementando un contador para cada elemento único en la lista e incrementándolo cada vez que se agrega un elemento ya existente. –

Respuesta

5

Esto es fácil de hacer a mano.

public int countNumberEqual(ArrayList<Item> itemList, Item itemToCheck) { 
    int count = 0; 
    for (Item i : itemList) { 
     if (i.equals(itemToCheck)) { 
      count++; 
     } 
    } 
    return count; 
} 

Tenga en cuenta que si no se sobreescribe equals en su clase Item, este método se utiliza la identidad del objeto (ya que esto es la implementación de Object.equals()).

Editar: En cuanto a su segunda pregunta (intente limitar las publicaciones a una pregunta cada una), puede hacerlo a mano también.

public List<Integer> indices(ArrayList<Item> items, Item itemToCheck) { 
    ArrayList<Integer> ret = new ArrayList<Integer>(); 
    for (int i = 0; i < items.size(); i++) { 
     if (items.get(i).equals(itemToCheck)) { 
      ret.add(i); 
     } 
    } 
    return ret; 
} 
+0

¿Hay algún otro método más eficaz porque mi lista contiene miles de elementos y un elemento en particular puede duplicarse como máximo 4 o 5 veces? Así que creo que no vale la pena comparar esos miles de artículos para encontrar esos 4 o 5 duplicados. No me sugiera que use 'Set' porque hay una razón sólida para no usar Set en mi caso. –

+1

Piense en el hecho de que para contar elementos necesitará de TODOS MODOS revisar toda la lista, ya que deberá verificarlos todos para conocer el recuento exacto. – Jack

+1

Si quiere algo que tiene una complejidad de tiempo menor, no tiene suerte; al no saber nada sobre el contenido de su Lista, debe verificar cada posición. Una optimización es comparar el 'hashCode' de su artículo con el' hashCode' de cada elemento en la Lista, pero si son iguales, entonces debe verificar la igualdad usando 'equals()' ya que su función hash puede tener colisiones. Si solo está buscando identidad de objeto, no hay necesidad de hacer esto ya que 'iguales' comparará las direcciones de memoria o algo similar. – danben

22

Puede utilizar Collections clase:

public static int frequency(Collection<?> c, Object o) 

Devuelve el número de elementos de la colección especificada igual al objeto especificado. Más formalmente, devuelve el número de elementos e en la colección de manera que (o == null? E == null: o.equals (e)).

Si es necesario contar las ocurrencias de una larga lista de muchas veces que sugerimos utilizar un HashMap para almacenar los contadores y actualizarlos mientras introduce nuevos elementos a la lista. Esto evitaría calcular cualquier tipo de contadores ... pero, por supuesto, no tendrá índices.

HashMap<Item, Integer> counters = new HashMap<Item, Integer>(5000); 
ArrayList<Item> items = new ArrayList<Item>(5000); 

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Una última pista: puede utilizar otro marco de las colecciones (como Apache Collections) y el uso de una estructura de datos Bag que se describe como

define una colección que cuenta el número de veces que un objeto aparece en la colección.

Así exactamente lo que necesita ..

+2

wow nunca supo acerca de este método. Javadoc encontrado aquí: http://java.sun.com/javase/6/docs/api/java/util/Collections.html#frequency%28java.util.Collection,%20java.lang.Objeto% 29 –

+0

Su primer método es más adecuado para mi necesidad. Pero hay un problema. Si encuentro más de un elemento en la lista, ¿cómo recuperar esos otros elementos de la lista? –

+2

Si son iguales, ¿por qué molestarse en recuperarlos? ¡Ya sabes lo que hay adentro! ¿O hay campos que no ingresan a su comparación 'iguales'? ¿O está buscando hacer algo más que solo recuperar, como eliminar? –

0

Como los otros encuestados han dicho ya, si está firmemente comprometido con el almacenamiento de sus artículos en un ArrayList desordenada, entonces contar los elementos tendrá un tiempo O (n) , donde n es la cantidad de elementos en la lista. ¡Aquí en SO, damos consejos pero no hacemos magia!

Como acabo de insinuar, si la lista se busca mucho más de lo que se modificó, podría tener sentido mantenerla ordenada.Si su lista está ordenada, puede encontrar su artículo en el tiempo O (log n), que es mucho más rápido; y si tiene una implementación hashcode que va bien con su equals, todos los elementos idénticos estarán uno al lado del otro.

Otra posibilidad sería crear y mantener dos estructuras de datos en paralelo. Puede usar un HashMap que contenga sus elementos como claves y su recuento como valores. Usted estaría obligado a actualizar esta segunda estructura cada vez que su lista cambie, pero las búsquedas de recuento de elementos serían o (1).

0

puedo estar equivocado, pero parece a mí como la estructura de datos que realmente desea podría ser un Multiset (de google-collections/guava) en lugar de un List. Permite múltiplos, a diferencia de Set, pero en realidad no le importa el orden. Dado que tiene un método int count(Object element) que hace exactamente lo que quiere. Y como no es una lista y tiene implementaciones respaldadas por un HashMap, obtener el recuento es considerablemente más eficiente.

0

Gracias por su muy buena sugerencia. Pero este código a continuación es realmente muy útil ya que no tenemos ningún método de búsqueda con la Lista que pueda dar el número de ocurrencia.

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Gracias a Jack. Buena publicación.

Gracias,

Binod Suman

http://binodsuman.blogspot.com

Cuestiones relacionadas