Подтвердить что ты не робот

Работа со списком списков в Java

Я пытаюсь прочитать CSV файл в списке списков (строк), передать его для получения некоторых данных из базы данных, построить новый список списков новых данных, а затем передать этот список списков, его можно записать в новый файл CSV. Я посмотрел на все, и я не могу найти пример того, как это сделать.

Я бы предпочел не использовать простые массивы, так как файлы будут отличаться по размеру, и я не буду знать, что использовать для размеров массивов. У меня нет проблем с файлами. Я просто не знаю, как обращаться со списком списков.

Большинство примеров, которые я нашел, будут создавать многомерные массивы или выполнять действия внутри цикла, которые считывают данные из файла. Я знаю, что могу это сделать, но хочу написать объектно-ориентированный код. Если бы вы могли предоставить некоторый пример кода или указать мне ссылку, это было бы здорово.

4b9b3361

Ответ 1

ArrayList<ArrayList<String>> listOLists = new ArrayList<ArrayList<String>>();
ArrayList<String> singleList = new ArrayList<String>();
singleList.add("hello");
singleList.add("world");
listOLists.add(singleList);

ArrayList<String> anotherList = new ArrayList<String>();
anotherList.add("this is another list");
listOLists.add(anotherList);

Ответ 2

Если вы действительно хотите знать, что файлы дескриптора CSV отлично работают на Java, нехорошо пытаться реализовать CSV-ридер/писатель самостоятельно. Проверьте ниже.

http://opencsv.sourceforge.net/

Когда ваш документ CSV включает в себя двойные кавычки или новые строки, вы столкнетесь с трудностями.

Чтобы сначала изучить объектно-ориентированный подход, вам поможет другая реализация (через Java). И я думаю, что это не очень хороший способ управлять одной строкой в ​​списке. CSV не позволяет иметь размер столбца разницы.

Ответ 3

Вот пример, который читает список строк CSV в списке списков, а затем перебирает список списков и выводит строки CSV на консоль.

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

        //pretend you're looping through lines in a file here
        for(String line : csvStrings)
        {
            String[] linePieces = line.split(",");
            List<String> csvPieces = new ArrayList<String>(linePieces.length);
            for(String piece : linePieces)
            {
                csvPieces.add(piece);
            }
            csvList.add(csvPieces);
        }

        //write the CSV back out to the console
        for(List<String> 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");
        }
    }
}

Довольно просто я думаю. Всего лишь пару замечаний:

  • Я рекомендую использовать "Список" вместо "ArrayList" с левой стороны при создании объектов списка. Лучше обойти интерфейс "Список", потому что если позже вам нужно будет изменить что-то вроде Vector (например, вам нужны синхронизированные списки), вам нужно только изменить строку с помощью "нового" оператора. Независимо от того, какую версию списка вы используете, например. Vector или ArrayList, вы все равно всегда просто обходите List<String>.

  • В конструкторе ArrayList вы можете оставить список пустым и по умолчанию будет иметь определенный размер, а затем динамически увеличиваться по мере необходимости. Но если вы знаете, насколько велик ваш список, вы иногда можете сэкономить некоторую производительность. Например, если вы знали, что в вашем файле всегда будет 500 строк, вы можете сделать следующее:

List<List<String>> csvList = new ArrayList<List<String>>(500);

Таким образом, вы никогда не потеряете время обработки, ожидая, что ваш список будет динамично расти. Вот почему я передаю конструктору конструкцию "linePieces.length". Обычно это не очень много, но иногда полезно.

Надеюсь, что это поможет!

Ответ 4

В примере, представленном @tster, показано, как создать список списка. Я приведу пример для итерации по такому списку.

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

Ответ 5

Что-то вроде этого будет работать для чтения:

String filename = "something.csv";
BufferedReader input = null;
List<List<String>> csvData = new ArrayList<List<String>>();
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();
    }
}

Ответ 6

Я бы повторил то, что сказал xrath - вам лучше использовать существующую библиотеку для обработки чтения/записи CSV.

Если вы планируете перематывать свою собственную фреймворк, я также предлагаю не использовать List<List<String>> в качестве вашей реализации - вам, вероятно, будет лучше реализовать классы CSVDocument и CSVRow (которые могут внутри себя использовать List<CSVRow> или List<String> соответственно), хотя для пользователей выставляют только неизменяемый список или массив.

Просто использование List<List<String>> оставляет слишком много случаев непроверенного края и опирается на детали реализации - например, являются ли заголовки хранятся отдельно от данных? или они находятся в первой строке List<List<String>>? Что делать, если я хочу получить доступ к данным по заголовку столбца из строки, а не по индексу?

что происходит, когда вы вызываете такие вещи, как:

// reads CSV data, 5 rows, 5 columns 
List<List<String>> 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.

Вы можете попытаться проверить все это при записи CSV файла, и это может работать в некоторых случаях... но в других случаях вы будете предупреждать пользователя об исключении, вдали от которого были сделаны ошибочные изменения, что приводит к сложной отладке.

Ответ 7

Также это пример того, как печатать список из списка, используя расширенный для цикла:

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