Работа со списком списков в Java
Я пытаюсь прочитать CSV файл в списке списков (строк), передать его для получения некоторых данных из базы данных, построить новый список списков новых данных, а затем передать этот список списков, его можно записать в новый файл CSV. Я посмотрел на все, и я не могу найти пример того, как это сделать.
Я бы предпочел не использовать простые массивы, так как файлы будут отличаться по размеру, и я не буду знать, что использовать для размеров массивов. У меня нет проблем с файлами. Я просто не знаю, как обращаться со списком списков.
Большинство примеров, которые я нашел, будут создавать многомерные массивы или выполнять действия внутри цикла, которые считывают данные из файла. Я знаю, что могу это сделать, но хочу написать объектно-ориентированный код. Если бы вы могли предоставить некоторый пример кода или указать мне ссылку, это было бы здорово.
Ответы
Ответ 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();
}
}