2012-04-25 8 views
7

Estoy buscando una estructura de datos Java similar a una ArrayList que cuando hago un add o un push con solo un argumento de valor, un índice me será devuelto automáticamente.ArrayList con índice devuelto en el valor de agregado

Por ejemplo:

ArrayList<String> elements = new ArrayList<String>(); 

String element = "foo"; 
String elementTwo = "bar"; 

int index1 = elements.add(element); //note this does not exist, i.e. returns bool in api 
int index2 = elements.add(elementTwo); 

System.out.println(elements.get(index1)); //would give "foo" 

pude ver escribir una clase envoltura alrededor de ArrayList que administra un contador que se incrementa en cada operación de adición y la invocación:

ArrayList.add(int index, E element) 

lo que realmente necesita para escribir una envoltura alrededor de ArrayList para esto? ¿Esto parece algo tan simple como para ser provisto de la caja en alguna parte?

Editar:

necesito el índice (tecla) para ser fijo y único para este caso de uso. Se sugirió un mapa y estoy de acuerdo con eso. ¿Alguien sabe de una implementación de mapa que le proporciona una clave generada automáticamente (únicamente) en una inserción de valor? Solo estoy tratando de decidir si necesito implementar mi propio contenedor para esto.

+2

'int index1 = elements.add (element) .size() - 1'; no funcionará – keety

+1

¿Qué pasa con 'int index1 = elements.size(); elements.add (elemento); '? – dasblinkenlight

+1

Estoy desconcertado. ¿Por qué es tan malo escribir una segunda línea para obtener la longitud actual? – paulsm4

Respuesta

5

El elemento se agregará al final de la lista. Entonces puede usar elements.size()-1 para obtener el nuevo índice de elementos.

Tenga en cuenta que esto no funcionará si múltiples hilos están modificando la lista al mismo tiempo.

EDIT: También tenga en cuenta que podría no ser una buena idea usar índice de un ArrayList s como un identificador único, ya que un índice de elementos se puede cambiar (por ejemplo cuando se quita un elemento o insertar uno nuevo utilizando add(int, Object)) . Si esto es un problema, depende de lo que quiera hacer con el índice: si solo lo necesita durante un tiempo breve después de agregar un elemento y puede estar seguro de que la lista no se modificará mientras tanto, no hay problema. En el otro caso, incluso un método que devuelva el índice al llamar al add(Object) no ayudaría porque el índice no se actualiza de todos modos. Para evitar este problema, puede:

  • Asegúrese de nunca eliminar elementos de la lista y nunca agregar elementos usando add(int, Object).
  • En lugar de eliminar elementos, también puede configurarlos en null utilizando el método set(int, null). De esta manera, ningún índice de elementos cambiará.
  • Usa alguna otra estructura de datos como, por ejemplo, un mapa con una ID personalizada como helloannalil sugiere en su respuesta.

EDIT 2: No he encontrado un caso, listo para usar la aplicación (pero esto no significa que no la hay, por supuesto). Para sugerir una buena solución, se necesita más información sobre el uso previsto de la estructura de datos, pero aquí hay algunas ideas y notas:

  • Si el número máximo de elementos no es grande, un ArrayList podrían utilizarse y el índice de elementos representa la ID. Como se indicó anteriormente, para eliminar un elemento se puede establecer en null para que no se cambien los índices. Al insertar, las posiciones con valores null pueden reutilizarse.
  • También puede utilizar uno de los dos métodos muestran en esta respuesta: https://stackoverflow.com/a/8939049/1347968 (palabras clave AtomicLong o IdentityHashMap)
  • hacer en no dependen de la "singularidad" de Object.hashCode() o System.identityHashCode(Object), ya que no está garantizada (probar por su ejecutando el ejemplo en la parte inferior de Suns/Oracles Bug #6321873).
+0

Gracias por la respuesta (+1). Yendo con un control de una respuesta con más detalles sobre la implementación de un mapa o la falta de eso. –

+0

@RyanR. Agregué algunas ideas y notas de implementación ... – siegi

+0

Me gusta la investigación. Ejecuté la clase HashClash. Interesante para ver romper la singularidad allí. No tengo 10 mil millones de ensayos en mi sistema, pero es bueno saberlo. –

2

bien lo que hago en que los casos (Me encanta ArrayLists) es conseguir el último índice preguntando al tamaño de la lista:

String thing = "theThing"; 
List<String> strList = new ArrayList<String>(); 
strList.add(thing); 
int indexOfThing = strList.size() - 1; 

quiero decir, es más fácil que poner en práctica su propia lista y solo funciona

2

si realmente desea esta función, se puede utilizar un mapa pero no enumerar

2

Sobre la base de sus comentarios y pregunta editado creo que se puede extender un HashMap para su uso como esto:

public class MyMap<V> extends HashMap<Integer, V> { 
    private static final long serialVersionUID = 1L; 
    public int add(V elem) { 
     int key = System.identityHashCode(elem); 
     super.put(key, elem); 
     return key; 
    } 
} 

Entonces dentro de su clase declarar MyMap así:

private MyMap<String> map = new MyMap<String>(); 

Y luego añadir sus elementos a MyMap así:

..... 
..... 
String element = "foo"; 
String elementTwo = "bar"; 
int index1 = map.add(element); 
int index2 = map.add(elementTwo); 

Ahora usted tienen index1 y index2 como índices de cuerdas se insertan que se pueden utilizar o pasar alrededor de la vida de su aplicación. Puede insertar o eliminar elementos en MyMap tantas veces que quieras, pero sus índices (index1 y index2) le va a devolver sus elementos insertados como esto:

String elem1 = map.get(index1); // will return "foo" 
String elem2 = map.get(index2); // will return "bar" 
+1

Buena respuesta (+1), esto cae bajo la parte "implementar mi propio envoltorio" de mi pregunta. Esperará un poco en el cheque, pero finalmente se lo dará si nadie más puede llegar a un enfoque de biblioteca más 'estándar'. ¿Curioso si esta es la manera más eficiente de hacer esto? ¿Quizás sería mejor escribir este tipo de cosas en una matriz de tamaño fijo si sabes que tienes un conjunto limitado de elementos? –

+0

Sí, de hecho, esto cae bajo la sección 'implementar mi propio envoltorio' de su pregunta. La OMI que utiliza cualquier arreglo o implementación basada en Colección requerirá mucho más código para que funcione, ya que agregará o eliminará elementos de ese almacenamiento. – anubhava

+0

@RyanR. Tenga en cuenta que esto no está garantizado para funcionar, según los Javadocs de ['System.identityHashCode (Object)'] (http://docs.oracle.com/javase/7/docs/api/java/lang/System. html) y ['Object.hashCode()'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html) la JVM no está obligada a devolver distintos códigos hash para objetos distintos La implementación depende de cómo quiera trabajar con su estructura de datos: con qué frecuencia agrega, elimina u obtiene elementos de ella, cuántos elementos habrá en ... Actualizaré mi respuesta más tarde, pero sería útil si proporcionara más información ... :-) – siegi

0
String thing = "theThing"; 
List<String> strList = new ArrayList<String>(); 
strList.add(thing); 
int indexOfThing = strList.size() - 1; 

Si eliminar un elemento, esto no se trabajo más largo.

+0

Por favor aprenda cómo agregar código a sus respuestas; http://stackoverflow.com/tour – krisdyson

Cuestiones relacionadas