¿Cómo puedo cortar un ArrayList de un ArrayList en Java?

80

¿Cómo obtengo una porción de matriz de un ArrayListen Java? Específicamente, quiero hacer algo como esto:

ArrayList<Integer> inputA = input.subList(0, input.size()/2);
// where 'input' is a prepouplated ArrayList<Integer>

Así que esperaba que esto funcionara, pero Java devuelve un List, por lo que es incompatible. Y cuando intento lanzarlo, Java no me deja. Necesito un ArrayList- ¿qué puedo hacer?

BT
fuente
4
¿Por qué insistes en usar un ArrayList? Creo que puede carecer de un poco de comprensión de cómo funcionan porque las interfaces Listy ArrayListno son “incompatibles” - ArrayListimplementos List, y Listprobablemente contiene todos los métodos necesarios que necesita.
Bombe
2
Insisto en usar ArrayList porque es una pregunta de entrevista con un prototipo de método rígido. Claramente tengo una falta de comprensión, porque se supone que subList devuelve un tipo de Lista y, sin embargo, no puedo enviar la Lista devuelta a ArrayList. Entonces dime hombre ...
BT
4
Es muy posible que necesite un ArrayListporque luego necesita llamar a un método con él que acepta un ArrayList. Podría decirse que este método está mal diseñado y debería aceptarse List, pero tales situaciones pueden surgir no solo en las preguntas de la entrevista, sino también en el código escrito por otros que uno no puede simplemente ir y cambiar. Los compañeros de trabajo y las bibliotecas no siempre son perfectos.
Gravity

Respuestas:

124

En Java, es una buena práctica utilizar tipos de interfaz en lugar de clases concretas en las API.

Tu problema es que estás usando ArrayList (probablemente en muchos lugares) donde realmente deberías usar List. Como resultado, se creó problemas con la restricción innecesaria de que la lista es unaArrayList .

Así es como debería verse su código:

List input = new ArrayList(...);

public void doSomething(List input) {
   List inputA = input.subList(0, input.size()/2);
   ...
}

this.doSomething(input);

Su "solución" propuesta al problema fue / es la siguiente:

new ArrayList(input.subList(0, input.size()/2))

Eso funciona haciendo una copia de la sublista. No es una tajada en el sentido normal. Además, si la sublista es grande, realizar la copia será costoso.


Si está limitado por las API que no puede cambiar , de modo que debe declarar inputAcomo una ArrayList, es posible que pueda implementar una subclase personalizada de ArrayListen la que el subListmétodo devuelve una subclase deArrayList . Sin embargo:

  1. Sería mucho trabajo diseñar, implementar y probar.
  2. Ahora ha agregado una nueva clase significativa a su base de código, posiblemente con dependencias de aspectos no documentados (y por lo tanto "sujetos a cambios") aspectos del ArrayList clase.
  3. Debería cambiar los lugares relevantes en su base de código donde está creando ArrayList instancias para crear instancias de su subclase en su lugar.

La solución "copiar la matriz" es más práctica ... teniendo en cuenta que estos no son cortes verdaderos.

Stephen C
fuente
6
En realidad, subList no hace una copia; devuelve una vista en la lista original ( docs.oracle.com/javase/6/docs/api/java/util/… )
Matt
3
En realidad, @Matthew, me refiero a la auto-respuesta del OP cuando hace esto:new ArrayList(input.subList(0, input.size()/2))
Stephen C
1
+1 para esta frase: en Java, es una buena práctica utilizar tipos de interfaz en lugar de clases concretas en las API.
Ilonpilaaja
6

He encontrado una manera si conoce startIndex y endIndex de los elementos que se deben eliminar de ArrayList

Dejado alser el ArrayList original y startIndex, endIndexser iniciar y índice de extremo a ser eliminado de la matriz, respectivamente:

al.subList(startIndex, endIndex + 1).clear();
Aman Gupta
fuente
6

Si no hay un método existente, supongo que puede iterar de 0 a input.size()/2 , tomando cada elemento consecutivo y anexándolo a una nueva ArrayList.

EDITAR : En realidad, creo que puede tomar esa Lista y usarla para crear una instancia de una nueva ArrayList usando uno de los constructores ArrayList .

Jorge Israel Peña
fuente
2
Eso es exactamente lo que hice (publiqué mi respuesta antes de leer su edición). Gracias
:)
Pero eso copia la Lista para hacer una nueva ArrayList.
Joren
2
@BT - Para que conste, eso no es lo que normalmente significa el término "rebanada" en este contexto.
Stephen C
2

Aunque esta publicación es muy antigua. En caso de que alguien esté buscando esto ...

Guava facilita la partición de la Lista en sublistas de un tamaño específico

List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
    List<List<Integer>> subSets = Lists.partition(intList, 3);
Hari Rao
fuente
Enlace rápido a la documentación de Guava Lists: google.github.io/guava/releases/19.0/api/docs/com/google/common/…
AryanJ-NYC
-4

Así es como lo resolví. Olvidé que la sublista era una referencia directa a los elementos de la lista original, por lo que tiene sentido por qué no funcionaría.

ArrayList<Integer> inputA = new ArrayList<Integer>(input.subList(0, input.size()/2));
BT
fuente