簡體   English   中英

在 Java 中使用列表列表

[英]Working with a List of Lists in Java

我正在嘗試將一個 CSV 文件讀入一個列表(字符串)列表,傳遞它以從數據庫中獲取一些數據,構建一個新數據列表的新列表,然后傳遞該列表列表以便它可以寫入新的 CSV 文件。 我已經看遍了,我似乎無法找到如何做到這一點的例子

我寧願不使用簡單的數組,因為文件的大小會有所不同,而且我不知道數組的維度使用什么。 我在處理文件方面沒有問題。 我只是不確定如何處理列表列表。

我發現的大多數示例都將創建多維數組或在從文件讀取數據的循環內執行操作。 我知道我可以做到,但我想編寫面向對象的代碼。 如果您能提供一些示例代碼或指向我的參考,那就太好了。

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

這是一個示例,它將 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");
        }
    }
}

我覺得很簡單。 只需要注意幾點:

  1. 創建列表對象時,我建議在左側使用“List”而不是“ArrayList”。 最好傳遞接口“List”,因為如果稍后您需要更改為使用類似 Vector 的東西(例如,您現在需要同步列表),您只需更改帶有“new”語句的行。 無論您使用哪種列表實現,例如 Vector 或 ArrayList,您仍然總是只傳遞List<String>

  2. 在 ArrayList 構造函數中,您可以將列表留空,它將默認為特定大小,然后根據需要動態增長。 但是如果你知道你的列表有多大,你有時可以節省一些性能。 例如,如果您知道文件中總會有 500 行,那么您可以執行以下操作:

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

這樣您就永遠不會浪費處理時間等待您的列表動態增長。 這就是我將“linePieces.length”傳遞給構造函數的原因。 通常沒什么大不了的,但有時會有所幫助。

希望有幫助!

如果你真的很想知道在Java中完美處理CSV文件,那么嘗試自己實現CSV讀寫器是不好的。 看看下面。

http://opencsv.sourceforge.net/

當您的 CSV 文檔包含雙引號或換行符時,您將面臨困難。

要首先學習面向對象的方法,查看其他實現(由 Java 實現)會對您有所幫助。 而且我認為在列表中管理一行不是一個好方法。 CSV 不允許您有不同的列大小。

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

像這樣的東西適合閱讀:

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

我贊同 xrath 所說的 - 你最好使用現有的庫來處理讀/寫 CSV。

如果您確實計划推出自己的框架,我還建議不要使用List<List<String>>作為您的實現 - 您最好實現CSVDocumentCSVRow類(可能在內部使用List<CSVRow>List<String> ),但對於用戶來說,只公開一個不可變的 List 或數組。

簡單地使用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 文件時嘗試驗證所有這些,這在某些情況下可能有效......但在其他情況下,您將警告用戶遠離進行錯誤更改的異常,從而導致調試困難。

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

        }
    }

}

這也是如何使用高級 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();
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM