Working with a List of Lists in Java

JavaArraysList

Java Problem Overview


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.

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.

Java Solutions


Solution 1 - Java

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);

Solution 2 - Java

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.

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:

  1. 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>.

  2. 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<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.

Hope that helps!

Solution 3 - Java

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.

http://opencsv.sourceforge.net/

When your CSV document includes double-quotes or newlines, you will face difficulties.

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.

Solution 4 - Java

The example provided by @tster shows how to create a list of list. I will provide an example for iterating over such a list.

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);
     }
}

Solution 5 - Java

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();
	}
}

Solution 6 - Java

I'd second what xrath said - you're better off using an existing library to handle reading / writing 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.

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?

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.

Solution 7 - Java

 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);
		     }
		     
		}
	}

}

Solution 8 - Java

Also this is an example of how to print List of List using advanced for loop:

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();
        }
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRob-0View Question on Stackoverflow
Solution 1 - JavatsterView Answer on Stackoverflow
Solution 2 - JavaBrent Writes CodeView Answer on Stackoverflow
Solution 3 - JavaxrathView Answer on Stackoverflow
Solution 4 - JavaVincent RamdhanieView Answer on Stackoverflow
Solution 5 - JavaDrooView Answer on Stackoverflow
Solution 6 - JavaNateView Answer on Stackoverflow
Solution 7 - Javajitendra rawatView Answer on Stackoverflow
Solution 8 - JavaMona JalalView Answer on Stackoverflow