【问题标题】:filling an bidimensionnal array in java在java中填充一个二维数组
【发布时间】:2013-09-16 19:45:57
【问题描述】:

我在从多维对象数组中填充双向双数组时遇到了一些问题。 我的问题是 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。 然后我正在填充一个名为sortedOutputdouble 二维数组,我想在其中存储LeftSpeedNormAvgPowOutput,它们是存储在我的Data 数组中的双值。

我想要什么: 让我的 sortedOutput bidimensionnal 数组在维度 0 上从最小值到最大值排序:对于变量 LeftSpeed

那么我怎样才能避免空值呢?因为当我在填充第二个数组时尝试发现它们时,编译器说我无法将双精度值与 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 != nullb != nulla[0] != nullb[0] != null)然后返回新订单。 (感谢@jboi)。

【问题讨论】:

  • 哪条线在抛出 NPE?
  • 如果你想要有用的 cmets,你真的需要发布完整的堆栈跟踪。
  • 你自己实现它有什么原因吗?有很好的开源库可以进行 CSV 解析。喜欢opencsv.sourceforge.net
  • 问题线是当我开始尝试启动我的数组时:`Arrays.sort(sortedOutput, new java.util.Comparator()`。这是因为其中一个值显然是null,但我不知道如何避免这种情况。

标签: java arrays nullpointerexception


【解决方案1】:

您正在崩溃,因为您在阅读所有条目之前对数组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]);
        }
     });

但是,我认为没有理由在每次输入后不断进行排序。

奇怪的是,在调用Arrays.sort() 之后,您还要检查数组元素是否为null,这要求它们不是null。如果您使用第二个选项,您至少需要将错误检查移到排序之前。

作为第三种选择,您可以在比较器中明确允许 null 数组条目。所有null 条目的排序应相同,并且应始终位于非null 条目之前或之后。

【讨论】:

  • 是的:o 你说得对,仍然崩溃,但我认为 @autra 完成了你的答案。
  • @trolologuy - 如果在您将调用移至循环之后它仍然崩溃,那么尽管进行了检查,您仍然允许null 条目。
  • @trolologuy - 在比较器内部,它只是if (a[0] == null) 等。如果您在null 检查期间打印FAIL,您可以考虑立即退出您的run() 方法。跨度>
【解决方案2】:

我从堆栈中看到的是,Double.compare(a[0], b[0]); 命令导致了 NullPointerException。这意味着,一二是null。作为一个快速解决方案,您可以使用以下命令更改命令:

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

这只能是快速和肮脏的,因为您需要了解为什么有 null、CSV 文件中的内容、使它们为 null 以及您如何处理此类数据。

【讨论】:

  • 我的 csv 文件由捕获者汇总的数据组成,有时值可以是 null(如果有错误,...),因此我可以简单地忽略这些结果,因为我需要从 csv 文件中绘制一条曲线。我没想到检查可以这么容易!谢谢:)
  • 循环之后,当我尝试按如下方式读取标签时 `k = 0; while (sortedOutput[k] != null) { System.out.println("速度 = " +sortedOutput[k][0]); System.out.println("Power = " +sortedOutput[k][2]); k++; } ` 但是当我在填充选项卡的循环中显示我的值时,这些值不是null
  • 奇怪。有问题,不在代码中,或者很明显,我看不到。您能否直接在return Double.compare... 之前签入comparator 并检查以下条件之一:a == null, b == null, a[0] == null, b[0] == null
  • @jboy 到目前为止没有任何变化,也许这只是我的显示器。我会尽力解决这个问题。
  • @jboy,好的,这个已经修好了,我的显示错误。现在这些值已正确排序:D 一切工作几乎完美。先生,你应该得到一块饼干(还有其他的):D 谢谢!
【解决方案3】:

首先,finally 子句在这里是相关的:您需要在此处调用流 br 的 close() 方法,以避免在异常情况下发生任何资源泄漏。

其次,我认为在这里使用数组而不是列表没有任何优势。在 java 中,我们在数组上使用列表(在这种情况下尤其是 ArrayList)。数组很少使用,不像在 C 中那样。Perfs 是完全一样的(如果你初始化你的列表的大小与你对数组的大小相同)。列表更好,因为它们为您提供更好的编译时检查,而数组仅提供运行时检查。 例如,下面的代码编译没有错误:

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

第三,当您遇到异常时,在此处发布完整的堆栈跟踪至关重要。如果人们有更好的信息,他们会给你更好的帮助!

幸运的是,在这里,我可以看到抛出 NPE 的位置:Double.compare 将两个 double 作为参数(而不是 Double)。因此,您的 Double 被自动装箱为双倍(谷歌“java autoboxing”),如果它们为空则抛出 NPE。您需要在比较器中处理 3 种无效情况(一种为 null,另一种为 null,另一种为 null)。或者,您可以在排序前删除空值。

【讨论】:

  • 首先:我不想发布我的完整代码,因为它会很长,但是在我的版本中,我确实关闭了文件;)其次:我需要存储 3 种不同的类型在我的数组(有很多列)中,这就是为什么我认为对象数组会更容易。第三:我编辑了我的帖子(对此感到抱歉)。感谢您的回答,我将尝试了解自动装箱并纠正我的错误。我想删除空值,但我不知道如何,因为当我试图查看该值是否为空时,编译器说我无法将双精度值与空值进行比较。也许你有另一个线索那个?
猜你喜欢
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
  • 2013-04-05
  • 2015-08-13
相关资源
最近更新 更多