web-dev-qa-db-ja.com

Javaのリストのリストの操作

私はCSVファイルを(文字列の)リストのリストに読み込み、データベースからデータを取得するためにそれを渡し、新しいデータのリストの新しいリストを作成し、次にそのリストを渡すことを試みています新しいCSVファイルに書き込まれます。 私はすべてを見てきたが、それを行う方法の例を見つけることができないようだ

ファイルのサイズはさまざまであり、配列の次元に何を使用すればよいかわからないため、単純な配列は使用しません。ファイルの処理に問題はありません。リストのリストをどのように扱うかがよくわかりません。

私が見つけた例のほとんどは、多次元配列を作成するか、ファイルからデータを読み取るループ内でアクションを実行します。私はそれができることを知っていますが、オブジェクト指向のコードを書きたいです。サンプルコードを提供したり、リファレンスを参照したりできれば、それは素晴らしいことです。

49
Rob-0
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);
129
tster

JavaでCSVファイルを完全に処理することを本当に知りたい場合は、CSVリーダー/ライターを自分で実装しようとするのは良くありません。以下をご覧ください。

http://opencsv.sourceforge.net/

CSVドキュメントに二重引用符または改行が含まれていると、問題が発生します。

最初にオブジェクト指向のアプローチを学ぶには、他の実装(Javaによる)を参照すると役立ちます。そして、リストの1行を管理するのは良い方法ではないと思います。 CSVでは、列のサイズを変えることはできません。

15
xrath

次に、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");
        }
    }
}

かなり簡単だと思います。注目すべき点は2、3です。

  1. リストオブジェクトを作成するときは、左側の「ArrayList」の代わりに「List」を使用することをお勧めします。インターフェース「リスト」を渡すことをお勧めします。後でベクターのようなものに変更する必要がある場合(たとえば、同期リストが必要になった場合)、「新しい」ステートメントで行を変更するだけです。使用するリストの実装に関係なく、たとえばVectorまたはArrayListの場合、常にList<String>を渡すだけです。

  2. ArrayListコンストラクターでは、リストを空のままにすると、デフォルトで特定のサイズに設定され、必要に応じて動的に拡大します。しかし、リストの大きさがわかっている場合は、パフォーマンスをある程度節約できます。たとえば、ファイルに常に500行あることがわかっている場合は、次のようにします。

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

そうすれば、リストが動的に成長するのを待って処理時間を無駄にすることはありません。これが、「linePieces.length」をコンストラクタに渡す理由です。通常は大したことではありませんが、時々役に立ちます。

お役に立てば幸いです!

11

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

Xrathが言ったことを2番目に言います-既存のライブラリを使用してCSVの読み取り/書き込みを処理する方が良いでしょう。

独自のフレームワークのローリングを計画している場合は、List<List<String>>を実装として使用しないこともお勧めします。CSVDocumentおよびCSVRowクラス(内部的にはList<CSVRow>またはList<String>をそれぞれ使用します)が、ユーザーに対しては、不変のリストまたは配列のみを公開します。

単にList<List<String>>を使用すると、未チェックのEdgeケースが多くなりすぎ、実装の詳細に依存します。たとえば、ヘッダーはデータとは別に保存されますか?または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ファイルを書き込むときにこれをすべて検証しようとすることができますが、これは場合によっては機能する可能性があります...しかし、間違った変更が行われた場所から遠く離れた例外をユーザーに警告することもあります難しいデバッグ。

2
Nate

また、これは、高度なforループを使用してList of Listを印刷する方法の例です。

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

        }
    }

}
0
jitendra rawat