Trabajando con una lista de listas en Java

Intento leer un archivo CSV en una lista de listas (de cadenas), pasarlo para obtener datos de una base de datos, crear una nueva lista de listas de datos nuevos y luego pasar esa lista de listas para que pueda ser escrito en un nuevo archivo CSV. He buscado todo, y parece que no puedo encontrar un ejemplo sobre cómo hacerlo .

Prefiero no usar arreglos simples ya que los archivos varían de tamaño y no sabré qué usar para las dimensiones de los arreglos. No tengo problemas para tratar con los archivos. Simplemente no estoy seguro de cómo lidiar con la lista de listas.

La mayoría de los ejemplos que he encontrado crearán matrices multidimensionales o realizarán acciones dentro del ciclo que está leyendo los datos del archivo. Sé que puedo hacerlo, pero quiero escribir código orientado a objetos. Si pudiera proporcionar algún código de ejemplo o señalarme una referencia, sería genial.

ArrayList> listOLists = new ArrayList>(); ArrayList singleList = new ArrayList(); singleList.add("hello"); singleList.add("world"); listOLists.add(singleList); ArrayList anotherList = new ArrayList(); anotherList.add("this is another list"); listOLists.add(anotherList); 

Si realmente desea saber que maneja los archivos CSV perfectamente en Java, no es bueno intentar implementar el lector / escritor CSV usted mismo. Verifique abajo.

http://opencsv.sourceforge.net/

Cuando su documento CSV incluye comillas dobles o nuevas líneas, enfrentará dificultades.

Para aprender el enfoque orientado a objetos al principio, ver otra implementación (por Java) te ayudará. Y creo que no es una buena forma de administrar una fila en una lista. CSV no le permite tener un tamaño de columna de diferencia.

Aquí hay un ejemplo que lee una lista de cadenas CSV en una lista de listas y luego recorre esa lista de listas e imprime las cadenas CSV en la consola.

 import java.util.ArrayList; import java.util.List; public class ListExample { public static void main(final String[] args) { //sample CSV strings...pretend they came from a file String[] csvStrings = new String[] { "abc,def,ghi,jkl,mno", "pqr,stu,vwx,yz", "123,345,678,90" }; List> csvList = new ArrayList>(); //pretend you're looping through lines in a file here for(String line : csvStrings) { String[] linePieces = line.split(","); List csvPieces = new ArrayList(linePieces.length); for(String piece : linePieces) { csvPieces.add(piece); } csvList.add(csvPieces); } //write the CSV back out to the console for(List csv : csvList) { //dumb logic to place the commas correctly if(!csv.isEmpty()) { System.out.print(csv.get(0)); for(int i=1; i < csv.size(); i++) { System.out.print("," + csv.get(i)); } } System.out.print("\n"); } } } 

Bastante sencillo, creo. Solo un par de puntos para notar:

  1. Recomiendo usar "List" en lugar de "ArrayList" en el lado izquierdo al crear objetos de lista. Es mejor pasar por la interfaz "Lista" porque luego, si necesita cambiar a usar algo como Vector (por ejemplo, ahora necesita listas sincronizadas), solo necesita cambiar la línea con la statement "nueva". Independientemente de la implementación de la lista que utilice, por ejemplo, Vector o ArrayList, siempre pasará List .

  2. En el constructor ArrayList, puede dejar la lista vacía y tendrá un tamaño predeterminado y luego crecer dinámicamente según sea necesario. Pero si sabe cuán grande puede ser su lista, a veces puede ahorrar algo de rendimiento. Por ejemplo, si supiera que siempre habrá 500 líneas en su archivo, entonces podría hacer:

List> csvList = new ArrayList>(500);

De esa forma, nunca perderás el tiempo de procesamiento esperando a que tu lista crezca de manera dinámica. Es por eso que paso "linePieces.length" al constructor. No suele ser un gran problema, pero a veces es útil.

¡Espero que ayude!

El ejemplo proporcionado por @tster muestra cómo crear una lista de listas. Proporcionaré un ejemplo para iterar sobre dicha lista.

 Iterator> iter = listOlist.iterator(); while(iter.hasNext()){ Iterator siter = iter.next().iterator(); while(siter.hasNext()){ String s = siter.next(); System.out.println(s); } } 

Algo como esto funcionaría para la lectura:

 String filename = "something.csv"; BufferedReader input = null; List> csvData = new ArrayList>(); try { input = new BufferedReader(new FileReader(filename)); String line = null; while (( line = input.readLine()) != null) { String[] data = line.split(","); csvData.add(Arrays.toList(data)); } } catch (Exception ex) { ex.printStackTrace(); } finally { if(input != null) { input.close(); } } 

En segundo lugar diría lo que dijo xrath: es mejor que utilices una biblioteca existente para manejar leer / escribir CSV.

Si planea implementar su propio marco de trabajo, también le sugiero que no use List> como su implementación; probablemente sea mejor que implemente las clases CSVDocument y CSVRow (que internamente puede usar una List o List respectivamente), aunque para los usuarios solo exponen una lista inmutable o una matriz.

El simple hecho de usar List> deja demasiados casos sin marcar y depende de los detalles de la implementación, por ejemplo, ¿los encabezados se almacenan por separado de los datos? o están en la primera fila de la List> ? ¿Qué pasa si quiero acceder a los datos por encabezado de columna desde la fila en lugar de por índice?

qué sucede cuando llamas cosas como:

 // reads CSV data, 5 rows, 5 columns List> csvData = readCSVData(); csvData.get(1).add("extraDataAfterColumn"); // now row 1 has a value in (nonexistant) column 6 csvData.get(2).remove(3); // values in columns 4 and 5 moved to columns 3 and 4, // attempting to access column 5 now throws an IndexOutOfBoundsException. 

Puede intentar validar todo esto al escribir el archivo CSV, y esto puede funcionar en algunos casos … pero en otros, alertará al usuario de una excepción muy lejos de donde se realizó el cambio erróneo, lo que resulta en depuración difícil.

También este es un ejemplo de cómo imprimir la Lista de listas usando el bucle avanzado para:

 public static void main(String[] args){ int[] a={1,3, 7, 8, 3, 9, 2, 4, 10}; List> triplets; triplets=sumOfThreeNaive(a, 13); for (List list : triplets){ for (int triplet: list){ System.out.print(triplet+" "); } System.out.println(); } }