1

多次元オブジェクト配列から 2 次元の double 配列を埋める際に問題が発生しています。私の問題は、null 値が を引き起こしていることでありjava.lang.NullPointerException at IOControl.ReadCSV$1.compare(ReadCSV.java:328) at IOControl.ReadCSV$1.compare(ReadCSV.java:1) at java.util.TimSort.countRunAndMakeAscending(Unknown Source) at java.util.TimSort.sort(Unknown Source) at java.util.TimSort.sort(Unknown Source) at java.util.Arrays.sort(Unknown Source) at IOControl.ReadCSV.run(ReadCSV.java:324) at en.window.Main.main(Main.java:46)、その理由が本当にわかりません。

私は何をやっている ? 私はCSVファイルを読んでいます。入力を行ごとに、オブジェクトの配列に保存していDataますcontent. 次に、格納したい、配列に格納されている double 値であるというdouble2 次元配列を埋めています。sortedOutputLeftSpeedNormAvgPowOutputData

私が欲しいもの: 私のsortedOutput二次元配列を次元0の最小値から最大値にソートするには:変数の場合LeftSpeed

では、どうすればヌル値を回避できますか? 2 番目の配列を埋めているときにそれらを見つけようとすると、コンパイラは double をnull値と比較できないと言うからです。

長い投稿で申し訳ありませんが、皆さんが私を助けてくれることを願っています:)ここに私のコード:

public void run(String path, int length) 
{
/* 
* Main function of ReadCSV class.
 * Open / reads / closes the file.
 * Fills the object.
 */

  BufferedReader br = null;
  String input = "";
  String cvsSplitBy = ",";
  int[] pos = new int[200];

  Data[] content = new Data[length];
  Double[][] sortedOutput = new Double[length][4];
  int i = 0;
  int j = 0;
  int k = 0;

  try 
  {
    br = new BufferedReader(new FileReader(path));
    while ((input = br.readLine()) != null) 
     {
       // use comma as separator
       String[] lines = input.split(cvsSplitBy);
       content[i] = new Data(); 
       if (i == 0)
       {
         //not relevant here                
       }
       else
       {
        j = 0;
        content[i].setTime("TIME", getTime(pos[j++], lines));
        content[i].setData("DATA", getContent(pos[j++], lines));
        //etc
       }
       // gets rid of non coherent or useless values, e.g negative power, ...
       if (content[i].lhWdStdev > 0 && content[i].rhWdStdev > 0)
       {
        normalizeData(content[i]); // not relevant
        content[k].setLeftSpeed();
        sortedOutput[k][0] = content[k].getLeftSpeed();
        sortedOutput[k][2] = content[k].getNormAvgPowOutput();
        Arrays.sort(sortedOutput, new java.util.Comparator<Double[]>()
        {
           public int compare(Double[]a, Double[]b)
           {
             return Double.compare(a[0], b[0]);
            }
         });
   }
   if (sortedOutput[k][0] == null)
   {
     System.out.println("FAIL");
   }
   System.out.println("Output = " +sortedOutput[k][0]);
   i++;
   k++;
 }
} 
catch (FileNotFoundException e) 
  {
    e.printStackTrace();
  } 
catch (IOException e) 
  {
    e.printStackTrace();
  } 
finally 
  {
  // Again it's not relevant
}

編集:最後に私は2つの大きな間違いを犯しました。最初に、ループ内で配列をソートしようとしました。つまり、配列が完全に満たされる前に (@Ted Hopp に感謝)。null第二に、値を正しく処理しませんでした。a != nullif ( , b != null, a[0] != null, )をチェックしてb[0] != nullから、新しい注文を返す必要がありました。(@jboiに感謝)。

4

3 に答える 3

2

sortedOutputすべてのエントリを読み取る前に配列をソートしているため、クラッシュしています。への呼び出しArrays.sort()は、入力を読み取っているループを通過するように移動する必要があります。

または、展開された引数リストを使用して呼び出しArrays.sort()て、並べ替える配列の量を制御することもできます。

Arrays.sort(sortedOutput, 0, k + 1, new java.util.Comparator<Double[]>()
    {
       public int compare(Double[]a, Double[]b)
       {
         return Double.compare(a[0], b[0]);
        }
     });

ただし、入力ごとに常にソートする理由はありません。

また、奇妙なことに、配列要素がではないことを要求するnull呼び出しの後に来る配列要素に対するチェックがあります。2 番目のオプションを使用する場合は、少なくともエラー チェックを並べ替えの前に移動する必要があります。Arrays.sort()null

null3 番目の方法として、コンパレータ内で配列エントリを明示的に許可することができます。すべてのエントリは同じように並べ替える必要があり、常に非エントリnullの前または後にある必要があります。null

于 2013-09-12T12:33:56.443 に答える
1

スタックトレースからわかることは、コマンドDouble.compare(a[0], b[0]);が NullPointerException を引き起こしているということです。つまり、2 つのうちの 1 つがnull. 簡単な解決策としてできることは、コマンドを次のように変更することです。

Double.compare((a[0]==null)? Double.NaN:a[0], (b[0]==null)? Double.NaN:b[0]);

null がある理由、CSV ファイルの内容、null になる理由、およびそのようなデータの処理方法を理解する必要があるため、これは迅速で汚いものにすぎません。

于 2013-09-12T12:45:39.520 に答える
0

まず第一に、finally 句はここで関連しています。例外が発生した場合のリソース リークを回避するために、そこでストリーム br の close() メソッドを呼び出す必要があります。

次に、ここでリストの代わりに配列を使用する利点はありません。Java では、配列よりもリスト (特にこの場合は ArrayList) を使用します。配列は、C とは異なり、めったに使用されません。Perfs はまったく同じです (配列と同じサイズでリストを初期化する場合)。リストはコンパイル時のチェックが優れているため、リストの方が優れていますが、配列はランタイムチェックのみを提供します。たとえば、次のコードはエラーなしでコンパイルされます。

String[] strings = new String[1];
Object[] objects = strings;
objects[0] = new Integer(1); 

第 3 に、例外が発生した場合は、完全なスタック トレースをここに投稿することが重要です。人々はより良​​い情報を持っていれば、より良いサポートを提供してくれるでしょう!

幸いなことに、ここで、NPE がスローされる場所を確認できます。Double.compare は、2 つの double を引数として取ります (Double ではありません)。したがって、Double は double にオートボックス化され (google "java autoboxing")、null の場合は NPE がスローされます。コンパレータで null の 3 つのケース (1 つは null、もう 1 つは両方、両方) を処理する必要があります。または、並べ替えの前に null 値を削除できます。

于 2013-09-12T12:28:50.180 に答える