Convierta ArrayList en una matriz 2D que contenga diferentes longitudes de matrices

Así que tengo:

ArrayList<ArrayList> 

Que contiene un número x de ArrayLists que contienen otro número de cadenas. Para demostrar:

 Index 0: String 1 String 2 String 3 Index 1: String 4 Index 2: Index 3: String 5 String 6 

Donde índice se refiere al índice de matriz que contiene una cadena.

¿Cómo puedo transformar esto en una matriz 2D que se ve así:

 {{String1, String2, String3},{String4}, {}, {String5, String6}} 

Muchas gracias.

 String[][] array = new String[arrayList.size()][]; for (int i = 0; i < arrayList.size(); i++) { ArrayList row = arrayList.get(i); array[i] = row.toArray(new String[row.size()]); } 

donde arrayList es su ArrayList> (o cualquier List> , cambie la primera línea dentro del bucle for según corresponda)

Bienvenido a un mundo con Java 8!

Solo me llevó toda la noche sin dormir para aprender lo que se necesitaba para escribir esta maldita línea de código. Estoy seguro de que ya está por ahí pero no pude encontrarlo. Así que estoy compartiendo mis horas y horas de investigación, disfruten. ¡Woot!

Asumiendo:

 ArrayList> mainList = new ArrayList>(); // populate this list here 

(O, mejor dicho, en Java 8:

 ArrayList> mainList = new ArrayList(); //Populate 

)

Entonces todo lo que necesitas es:

 String[][] stringArray = mainList.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);` 

Bam! Una línea.

No estoy seguro de qué tan rápido se compara con las otras opciones. Pero así es como funciona:

  1. Tome una secuencia de mainList 2D ArrayList. Esta secuencia es un poco como un Vector conectado con una LinkedList y tuvieron un hijo. Y ese niño, más adelante en la vida, recibió algo de NZT-48 . Estoy divagando; mainList.stream() devuelve una secuencia de elementos ArrayList . O incluso en lenguaje más geek: mainList.stream() devuelve un Stream> , sorta.

  2. Llame a la función .map en esa secuencia que devolverá una nueva secuencia con contenidos que coincidan con un nuevo tipo especificado por los parámetros pasados ​​al map . Esta función de map encubrirá cada elemento en nuestra secuencia para nosotros. Tiene una statement foreach incorporada. Para lograr esto; la función de map toma una expresión lambda como su parámetro. Una expresión Lambda es como una simple función en línea de una línea. Que tiene dos tipos de datos obteniendo Jiggy con esto . Primero es el tipo de datos en la secuencia sobre la que se llamó ( mainList.stream() ). El siguiente tipo es el tipo de datos al que se asignará, que está en la mitad derecha de la expresión lambda: u -> u.toArray(new String[0]) . Aquí u es un identificador que elige al igual que cuando usa una statement foreach . La primera mitad lo declara así: u -> . Y como un foreach , la variable u ahora será cada elemento en la secuencia a medida que recorre la secuencia. Por lo tanto, u es del tipo de datos que los elementos de la secuencia original son porque son ellos. La mitad derecha de la expresión Lambda muestra qué hacer con cada elemento: u.toArray(new String[0]) . Con los resultados almacenados en el lugar que les corresponde en una nueva transmisión. En este caso, lo convertimos en String[] .. porque, después de todo, se trata de una matriz 2D de String … o más bien desde este punto en el código, una matriz 1D de String[] (matrices de cadenas). Tenga en cuenta que, en última instancia, es un ArrayList . Tenga en cuenta que llamar a toArray desde un objeto ArrayList creará una nueva matriz del tipo que se le pasa. Aquí pasamos un new String[0] . Por lo tanto, crea una nueva matriz de tipo String[] y con una longitud igual a la longitud de ArrayList u . A continuación, rellena este nuevo conjunto de cadenas con los contenidos de ArrayList y lo devuelve. Lo cual deja la expresión Lambda y regresa al map . Luego, el map recostack estas matrices de cadenas y crea una nueva secuencia con ellas, tiene el tipo asociado String[] y luego lo devuelve. Por lo tanto, el map devuelve un Stream , en este caso. (Bueno, en realidad devuelve un Stream , que es confuso y necesita conversión, ver más abajo)

  3. Por lo tanto, solo debemos llamar a toArray en esa nueva secuencia de matrices de cadenas. Pero llamar a toArray en Stream es un poco diferente que invocarlo en una ArrayList , como lo hicimos antes. Aquí, tenemos que usar una cosa de confusión de referencia de función. Toma el tipo de esto: String[][]::new . Esa new función tiene tipo String[][] . Básicamente, dado que la función se llama aArray , siempre será un [] de algún tipo. En nuestro caso, dado que los datos en el interior eran otra matriz, simplemente agregamos otro [] . No estoy seguro de por qué el NZT-48 no estaba trabajando en este. Hubiera esperado que una llamada predeterminada a toArray() fuera suficiente, ya que es una secuencia y todo. Una transmisión que es específicamente Stream . ¿Alguien sabe por qué el map realmente devuelve un Stream y no una secuencia del tipo devuelto por la expresión Lambda dentro?

  4. Ahora que tenemos el toArray de nuestra transmisión mainList actuando correctamente. Podemos simplemente volcarlo en una variable local lo suficientemente fácil: String[][] stringArray = mainList.stream...

Convierta 2D ArrayList de enteros a 2D array de primitivos ints

Ahora, sé que algunos de ustedes van por ahí. “¡Esto no funciona para los ints!” Como era mi caso. Sin embargo, funciona para ” Ents “, ver arriba. Pero, si desea una matriz int primitiva 2D a partir de una ArrayList de Integer 2D (es decir, ArrayList> ). Tienes que cambiar alrededor de la cartografía del medio [tierra]. Tenga en cuenta que ArrayLists no puede tener tipos primitivos. Por lo tanto, no puede llamar a toArray en ArrayList y esperar obtener un int[] . Necesitarás mapearlo … otra vez.

 int[][] intArray = mainList.stream().map( u -> u.stream().mapToInt(i->i).toArray() ).toArray(int[][]::new); 

Intenté espaciarlo para que fuera legible. Pero puede ver aquí que tenemos que pasar por el mismo proceso de mapeo completo nuevamente. Esta vez no podemos simplemente llamar a toArray en ArrayList u ; como en el ejemplo anterior. Aquí llamamos a toArray on a Stream no a ArrayList . Entonces, por alguna razón, no tenemos que pasarle un “tipo”, creo que es tomar esteroides cerebrales. Por lo tanto, podemos tomar la opción predeterminada; donde se necesita un golpe de ese NZT-48 y se da cuenta de lo obvio para nosotros este [tiempo de ejecución]. No estoy seguro de por qué no podría hacer eso en el ejemplo anterior. Oh, eso es correcto … ArrayLists no toma NZT-48 como las Streams do. Espera … ¿de qué estoy hablando aquí?

Annnyhoow, porque las transmisiones son taaaan inteligentes. Al igual que Sheldon , necesitamos un protocolo completamente nuevo para tratar con ellos. La inteligencia aparentemente avanzada no siempre significa fácil de tratar. Por lo tanto, este nuevo mapToInt es necesario para crear un nuevo Stream que podemos utilizar de forma más inteligente para toArray . Y la expresión i->i Lambda en mapToInt es un simple unboxing del Integer a int , utilizando el auto-unboxing implícito que permite int = Integer . Lo cual, ahora, parece una tontería trivial, como si la inteligencia tuviera sus límites. Durante mi aventura, aprendí todo esto: de hecho, traté de usar mapToInt(null) porque esperaba un comportamiento predeterminado. ¡No es una discusión! ( tos Sheldon tos ) Entonces digo en mi mejor acento chica Husker Valley, “Después de todo, se llama mapToInt , me imagino que, como, el 84% del tiempo ( 42 x2) será, como, pasó i->i por, como, todos, así que, como, omgawd! ” No hace falta decir que me siento un poco … como … este tipo . ¡No sé por qué no funciona de esa manera!

Bueno, soy ojos rojos, medio delirante y medio dormido. Probablemente cometí algunos errores; por favor trollos para que pueda arreglarlos y decirme si hay una manera aún mejor!

PT

Puede usar el método toArray() para convertir una ArrayList en una matriz. Como tiene ArrayList dentro de ArrayList, deberá iterar sobre cada elemento y aplicar este método.

Algo como esto:-

 ArrayList> mainList = new ArrayList>(); // populate this list here //more code // convert to an array of ArrayLists ArrayList tempList = new ArrayList(); for (ArrayList stringList : mainList){ tempList.add((String[])stringList.toArray()); } //Convert to array of arrays - 2D array String [][]list = (String[][])tempList.toArray(); 

Puede encontrar más información sobre toArray() aquí.

 ArrayList> list= new ArrayList>(); ArrayList a = new ArrayList(); ArrayList b = new ArrayList(); a.add("Hello"); b.add("Hell"); list.add(a); list.add(b); Object[][] array = new Object[list.size()][]; Iterator> iterator = list.iterator(); int i = 0; while(iterator.hasNext()){ array[i] = iterator.next().toArray(); } 

Puede usar el siguiente fragmento para convertir Object [] en String []

 String[] stringArray = Arrays.copyOf(objectArray, objectArray.length, String[].class); 

Por ejemplo:

 public String[][] toArray(List> list) { String[][] r = new String[list.size()][]; int i = 0; for (List next : list) { r[i++] = next.toArray(new String[next.size()]); } return r; } 

Este mini código de progtwig completo responde a esta pregunta de forma bastante autoexplicativa. Solo péguelo y ejecútelo:

 import java.util.ArrayList; import java.util.List; public class ListTo2Darray { public String[][] toArray(List> list) { String[][] r = new String[list.size()][]; int i = 0; for (List next : list) { r[i++] = next.toArray(new String[next.size()]); } return r; } public static void main(String[]arg){ String[][] sham; List> mList = new ArrayList(); List a= new ArrayList(); List b= new ArrayList(); a.add("a"); a.add("a"); b.add("b"); b.add("b"); mList.add(a); mList.add(b); ListTo2Darray mt= new ListTo2Darray(); sham= mt.toArray(mList); System.out.println(sham[0][0]); System.out.println(sham[0][1]); System.out.println(sham[1][0]); System.out.println(sham[1][1]); } }