2012-04-06 12 views
14

Così ho:Converti ArrayList in una matrice 2D contenente diverse lunghezze di array

ArrayList<ArrayList<String>> 

che contiene un numero x di ArrayLists che contengono un altro numero y di stringhe .. Per dimostrare:

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

Dove indice fa riferimento all'indice della matrice che contiene una stringa.

Come posso trasformare questa in una matrice 2D che assomiglia a:

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

Grazie mille.

risposta

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

dove arrayList è il vostro ArrayList<ArrayList<String>> (o qualsiasi List<List<String>>, cambiare la prima linea all'interno del ciclo for di conseguenza)

+1

Cosa se ho ArrayList e voglio convertirlo in un 2D array? – shridatt

+3

scusate, questo mi è sfuggito, forse ora lo avete capito ... In ogni caso, è semplicemente 'String [] [] array2D = new String [arrayList.size()] []; per (int i = 0; i

5

È possibile utilizzare il metodo toArray() per convertire un ArrayList in un array. Dato che hai ArrayList all'interno di ArrayList, dovrai eseguire iterazioni su ogni elemento e applicare questo metodo.

Qualcosa di simile a questo: -

ArrayList<ArrayList<String>> mainList = new ArrayList<ArrayList<String>>(); 
// populate this list here 
//more code 

// convert to an array of ArrayLists 
ArrayList<String[]> tempList = new ArrayList<String[]>(); 
for (ArrayList<String> stringList : mainList){ 
    tempList.add((String[])stringList.toArray()); 
} 

//Convert to array of arrays - 2D array 
String [][]list = (String[][])tempList.toArray(); 

È possibile trovare maggiori informazioni su toArray()here.

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

È possibile utilizzare il frammento di seguito per convertire Object [] per String []

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

Ad esempio:

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

Benvenuti in un mondo con Java 8!

Mi ci è voluto solo tutta la notte senza dormire per imparare che cosa era necessario per scrivere questa linea di codice sconvolgente. Sono sicuro che sia già là fuori da qualche parte ma non riuscivo a trovarlo. Quindi sto condividendo le mie ore e ore di ricerca, mi diverto. Woot!

Assumendo:

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

(O, meglio, in Java 8:

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

)

Poi tutto quello che serve è:

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

Bam! Una linea.

Non sono sicuro di quanto sia veloce rispetto alle altre opzioni. Ma questo è come funziona:

  1. Prendere un flusso del mainList 2D ArrayList. Questo flusso è un po 'come un Vector collegato a una LinkedList e hanno avuto un bambino.E quel ragazzo, più tardi nella vita, si è schiacciato su un po 'di NZT-48. Io divago; mainList.stream() restituisce un flusso di elementi ArrayList<String>. O anche in un linguaggio più geeker: mainList.stream() restituisce un Stream<ArrayList<String>>, sorta.

  2. Chiama la funzione .map su quel flusso che restituirà un nuovo flusso con contenuti che corrispondono a un nuovo tipo specificato dai parametri passati in map. Questa funzione map coprirà per noi ogni elemento nel nostro stream. Ha una dichiarazione integrata foreach. Per realizzare questo; la funzione map accetta un'espressione lambda come parametro. A Lambda expression è come una semplice funzione a linea singola. Quale ha due tipi di dati gettin' Jiggy wit it. Il primo è il tipo di dati nello stream su cui è stato chiamato (mainList.stream()). Il prossimo tipo è il tipo di dati a cui verrà mappato, che si trova nella metà destra dell'espressione lambda: u -> u.toArray(new String[0]). Qui u è un identificatore scelto proprio come quando si utilizza un'istruzione foreach. Il primo semestre lo dichiara così: u ->. E come un foreach, la variabile u sarà ora ogni elemento nel flusso mentre itera attraverso il flusso. Pertanto, u è del tipo di dati che gli elementi del flusso originale sono perché esso è. La metà destra dell'espressione Lambda mostra cosa fare con ciascun elemento: u.toArray(new String[0]). Con i risultati memorizzati nella loro giusta posizione in un nuovo stream. In questo caso lo convertiamo in un String[] .. perché dopo tutto, questo è un array 2D di String .. o meglio da questo punto nel codice, un array 1D di String[] (string array). Tieni presente che lo u è in definitiva un ArrayList. Nota: chiamando toArray da un oggetto ArrayList verrà creato un nuovo array del tipo passato in esso. Qui passiamo in new String[0]. Pertanto crea una nuova matrice di tipo String[] e con lunghezza pari alla lunghezza di ArrayList u. Quindi riempie questa nuova serie di stringhe con il contenuto dello ArrayList e lo restituisce. Che lascia l'espressione Lambda e torna a map. Quindi, map raccoglie questi array di stringhe e crea un nuovo flusso con essi, ha il tipo associato String[] e quindi lo restituisce. Pertanto, map restituisce uno Stream<String[]>, in questo caso. (Beh, in realtà restituisce un Stream<Object[]>, che è fonte di confusione e ha bisogno di conversione, vedi sotto)

  3. Quindi abbiamo solo bisogno di chiamare toArray su quel nuovo flusso di array di stringhe. Ma chiamare toArray su un Stream<Object[]> è leggermente diverso dal chiamarlo su un ArrayList<String>, come abbiamo fatto prima. Qui, dobbiamo usare una cosa che confonde la funzione di riferimento. Prende il tipo da questo: String[][]::new. La funzione new ha il tipo String[][]. Fondamentalmente, poiché la funzione è chiamata perArray, sarà sempre un [] di qualche tipo. Nel nostro caso, dato che i dati all'interno erano ancora un altro array, aggiungiamo semplicemente un altro []. Non sono sicuro del motivo per cui la NZT-48 non ha funzionato su questo. Mi sarei aspettato che una chiamata predefinita a toArray() sarebbe stata sufficiente, visto che è un flusso e tutto. Un flusso che è specificamente Stream<String[]>. Qualcuno sa perché lorestituisce effettivamente un Stream<Object[]> e non un flusso del tipo restituito dall'espressione Lambda all'interno?

  4. Ora che abbiamo il toArray dal nostro stream mainList che funziona correttamente.Possiamo solo il dump in una variabile locale abbastanza facile: String[][] stringArray = mainList.stream...

Convert 2D ArrayList di interi a matrice 2D di int primitivi

Ora, so che alcuni di voi sono là fuori corso. "Questo non funziona per ints!" Come è stato il mio caso. Funziona comunque per "Ents", vedi sopra. Ma, se si desidera una matrice 2D primitiva int da un 2D ArrayList di Integer (ad esempio ArrayList<ArrayList<Integer>>). Devi cambiare attorno alla mappatura di mezzo [terra]. Tieni presente che le liste di array non possono avere tipi primitivi. Pertanto non è possibile chiamare toArray su ArrayList<Integer> e aspettarsi di ottenere uno int[]. Dovrai mapparlo di nuovo ... di nuovo.

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

Ho provato a spaziarlo per la leggibilità. Ma qui puoi vedere che dobbiamo ripetere lo stesso intero processo di mappatura. Questa volta non possiamo semplicemente chiamare toArray su ArrayList u; come con l'esempio precedente. Qui stiamo chiamando toArray su un Stream non uno ArrayList. Quindi per qualche ragione non dobbiamo passare un "tipo", penso che stia prendendo steroidi cerebrali. Pertanto, possiamo prendere l'opzione predefinita; dove ci vuole un colpo di quel NZT-48 e capisce l'ovvio per noi questa [corsa] tempo. Non sono sicuro del motivo per cui non è stato possibile farlo nell'esempio sopra. Oh, giusto ... Le liste di array non accettano NZT-48 come fanno gli Stream. Aspetta ... di cosa sto parlando?

Annnyhoow, perché i flussi sono così intelligenti. Come Sheldon, abbiamo bisogno di un protocollo completamente nuovo per gestirli. L'intelligenza apparentemente avanzata non sempre significa facile da gestire. Pertanto, questo nuovo mapToInt è necessario per creare un nuovo che possiamo usare più intelligente toArray. E l'espressione lambda i->i in mapToInt è un semplice annullamento automatico di Integer a int, utilizzando l'auto-unboxing implicito che consente int = Integer. Che, ora, sembra una sciocchezza da fare, come se l'intelligenza avesse i suoi limiti. Durante la mia avventura, ho imparato tutto questo: ho effettivamente provato a usare mapToInt(null) perché mi aspettavo un comportamento predefinito. Non un argomento !! (tosse Sheldon tosse) allora io dico nel mio miglior ragazza accento Husker valle, "Dopotutto, è chiamato mapToInt, direi che, come, l'84% del tempo (42 x2) sarà, come, passato i->i da, come, tutti, così come, omgawd! " Inutile dire che mi sento un po '... come ... this guy. Non so perché non funziona in questo modo!

Beh, sono gli occhi rossi e mezzo delirante e mezzo addormentato. Probabilmente ho fatto degli errori; per favore li troll, così posso sistemarli e farmi sapere se c'è un modo ancora migliore!

PT

+0

Dato che' map' accetta un Lambda (che conosce il tipo di dati di ciascun lato del Lambda), dovrebbe essere in grado di passare le informazioni sul tipo di dati in poi. Quindi, nonostante le mie folle chiacchierate, vorrei ancora una risposta a queste due domande menzionate sopra: 1) Perché 'map' restituisce effettivamente un' Stream 'come comportamento predefinito e non un flusso del tipo restituito dal Espressione Lambda dentro? --- 2) Perché 'mapToInt' non ha un uso predefinito di' i-> i'? –

0

Questo codice completo programma di mini risponde a questa domanda in modo del tutto pasta way.Just auto-esplicativo ed eseguirlo:

import java.util.ArrayList; 
import java.util.List; 

public class ListTo2Darray { 

    public String[][] toArray(List<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<List<?>> mList = new ArrayList(); 

     List<String> a= new ArrayList(); 
     List<String> 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]); 
    } 

} 
Problemi correlati