在 Java 中使用列表列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1474954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Working with a List of Lists in Java
提问by
I'm trying to read a CSV file into a list of lists (of strings), pass it around for getting some data from a database, build a new list of lists of new data, then pass that list of lists so it can be written to a new CSV file. I've looked all over, and I can't seem to find an example on how to do it.
我正在尝试将一个 CSV 文件读入一个列表(字符串)列表中,传递它以从数据库中获取一些数据,构建一个新数据列表的新列表,然后传递该列表列表以便它可以写入新的 CSV 文件。我已经看遍了,我似乎无法找到如何做到这一点的例子。
I'd rather not use simple arrays since the files will vary in size and I won't know what to use for the dimensions of the arrays. I have no issues dealing with the files. I'm just not sure how to deal with the list of lists.
我宁愿不使用简单的数组,因为文件的大小会有所不同,而且我不知道数组的维度使用什么。我在处理文件方面没有问题。我只是不确定如何处理列表列表。
Most of the examples I've found will create multi-dimensional arrays or perform actions inside the loop that's reading the data from the file. I know I can do that, but I want to write object-oriented code. If you could provide some example code or point me to a reference, that would be great.
我发现的大多数示例都将创建多维数组或在从文件读取数据的循环内执行操作。我知道我可以做到,但我想编写面向对象的代码。如果您能提供一些示例代码或指向我的参考,那就太好了。
回答by tster
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);
回答by Brent Writes Code
Here's an example that reads a list of CSV strings into a list of lists and then loops through that list of lists and prints the CSV strings back out to the console.
这是一个示例,它将 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");
}
}
}
Pretty straightforward I think. Just a couple points to notice:
我觉得很简单。只需要注意几点:
I recommend using "List" instead of "ArrayList" on the left side when creating list objects. It's better to pass around the interface "List" because then if later you need to change to using something like Vector (e.g. you now need synchronized lists), you only need to change the line with the "new" statement. No matter what implementation of list you use, e.g. Vector or ArrayList, you still always just pass around
List<String>
.In the ArrayList constructor, you can leave the list empty and it will default to a certain size and then grow dynamically as needed. But if you know how big your list might be, you can sometimes save some performance. For instance, if you knew there were always going to be 500 lines in your file, then you could do:
创建列表对象时,我建议在左侧使用“List”而不是“ArrayList”。最好传递接口“List”,因为如果稍后您需要更改为使用类似 Vector 的东西(例如,您现在需要同步列表),您只需更改带有“new”语句的行。无论您使用哪种列表实现,例如 Vector 或 ArrayList,您仍然总是只传递
List<String>
.在 ArrayList 构造函数中,您可以将列表留空,它将默认为特定大小,然后根据需要动态增长。但是如果你知道你的列表有多大,你有时可以节省一些性能。例如,如果您知道文件中总会有 500 行,那么您可以执行以下操作:
List<List<String>> csvList = new ArrayList<List<String>>(500);
List<List<String>> csvList = new ArrayList<List<String>>(500);
That way you would never waste processing time waiting for your list to grow dynamically grow. This is why I pass "linePieces.length" to the constructor. Not usually a big deal, but helpful sometimes.
这样您就永远不会浪费处理时间等待您的列表动态增长。这就是我将“linePieces.length”传递给构造函数的原因。通常没什么大不了的,但有时会有所帮助。
Hope that helps!
希望有帮助!
回答by Vincent Ramdhanie
The example provided by @tster shows how to create a list of list. I will provide an example for iterating over such a list.
@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);
}
}
回答by xrath
If you are really like to know that handle CSV files perfectly in Java, it's not good to try to implement CSV reader/writer by yourself. Check below out.
如果你真的很想知道在Java中完美处理CSV文件,那么尝试自己实现CSV读写器是不好的。看看下面。
http://opencsv.sourceforge.net/
http://opencsv.sourceforge.net/
When your CSV document includes double-quotes or newlines, you will face difficulties.
当您的 CSV 文档包含双引号或换行符时,您将面临困难。
To learn object-oriented approach at first, seeing other implementation (by Java) will help you. And I think it's not good way to manage one row in a List. CSV doesn't allow you to have difference column size.
要首先学习面向对象的方法,查看其他实现(由 Java 实现)会对您有所帮助。而且我认为在列表中管理一行不是一个好方法。CSV 不允许您有不同的列大小。
回答by Nate
I'd second what xrath said - you're better off using an existing library to handle reading / writing CSV.
我赞同 xrath 所说的 - 你最好使用现有的库来处理读/写 CSV。
If you do plan on rolling your own framework, I'd also suggest not using List<List<String>>
as your implementation - you'd probably be better off implementing CSVDocument
and CSVRow
classes (that may internally uses a List<CSVRow>
or List<String>
respectively), though for users, only expose an immutable List or an array.
如果您确实计划推出自己的框架,我还建议不要将其List<List<String>>
用作您的实现 - 您可能最好实现CSVDocument
和CSVRow
类(可能在内部使用 aList<CSVRow>
或List<String>
分别),但对于用户来说,只公开一个不可变的 List或数组。
Simply using List<List<String>>
leaves too many unchecked edge cases and relying on implementation details - like, are headers stored separately from the data? or are they in the first row of the List<List<String>>
? What if I want to access data by column header from the row rather than by index?
简单地使用List<List<String>>
留下太多未经检查的边缘情况并依赖于实现细节 - 例如,标头是否与数据分开存储?还是他们在第一排List<List<String>>
?如果我想通过行中的列标题而不是索引访问数据怎么办?
what happens when you call things like :
当您调用以下内容时会发生什么:
// 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.
You could attempt to validate all this when writing out the CSV file, and this may work in some cases... but in others, you'll be alerting the user of an exception far away from where the erroneous change was made, resulting in difficult debugging.
您可以在写出 CSV 文件时尝试验证所有这些,这在某些情况下可能有效......但在其他情况下,您将警告用户远离进行错误更改的异常,从而导致调试困难。
回答by Droo
Something like this would work for reading:
像这样的东西适合阅读:
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();
}
}
回答by Mona Jalal
Also this is an example of how to print List of List using advanced for loop:
这也是如何使用高级 for 循环打印列表列表的示例:
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();
}
}
回答by jitendra rawat
public class TEst {
public static void main(String[] args) {
List<Integer> ls=new ArrayList<>();
ls.add(1);
ls.add(2);
List<Integer> ls1=new ArrayList<>();
ls1.add(3);
ls1.add(4);
List<List<Integer>> ls2=new ArrayList<>();
ls2.add(ls);
ls2.add(ls1);
List<List<List<Integer>>> ls3=new ArrayList<>();
ls3.add(ls2);
methodRecursion(ls3);
}
private static void methodRecursion(List ls3) {
for(Object ls4:ls3)
{
if(ls4 instanceof List)
{
methodRecursion((List)ls4);
}else {
System.out.print(ls4);
}
}
}
}