【问题标题】:Error in checking ArrayList elements (extracted from a csv file) in Java and parsing them using the required logic在 Java 中检查 ArrayList 元素(从 csv 文件中提取)并使用所需逻辑解析它们时出错
【发布时间】:2015-11-08 10:43:48
【问题描述】:

我读取了一个 CSV 文件,如下所示。

,Tmt 1,Tmt 2,Tmt 3
delta 1,-104,-100,-103
delta 2,-125,-103,-103
delta 3,-104,-100,failed

后来,我解析了 csv 文件并将其所有元素放入字符串的 ArrayList。 现在 ArrayList 看起来像

[Tmt 1, Tmt 2, Tmt 3, delta 1, -104, -100, -103, delta 2, -125, -103, -103, delta 3, -104, -100, failed]

现在,我想删除以字母开头的 String ArrayList(如上所示)的所有元素。我使用以下代码来做到这一点。 (al1 是我上面提到的 ArrayList,temp 是我用来检查 al1 元素的字符串)

for(int i=0;i<al1.size();i++)
  {   
    temp = al1.get(i);  
    if (temp.charAt(0)=='-'|| (Character.isDigit(temp.charAt(0))==false))
           {
               al1.remove(i);    
           }    
  }
System.out.print(al1); 

现在代码运行后希望删除 al1 中以字母开头的元素,我打印了 ArrayList al1,结果如下:

[Tmt 2, delts 1, -100, delta 2, -103, delta 3, -100]

(这不是我所期望的)

请帮忙..提前谢谢

【问题讨论】:

  • 嗯,你期望做了什么,为什么?您是否使用调试器逐步完成此操作,并找出问题所在?您是否确定问题出在使用列表还是字符串处理上?要记住的一件事:如果您从列表中删除一个项目,其他所有内容都会随机排列...因此您要检查的下一个项目将与您刚刚删除的项目具有 same 索引。您可以通过在 remove 调用之后添加 i-- 来解决此问题。或者,您可以从列表的结尾一直到开头。
  • 或者你可以创建另一个列表,只包含你想要保留的元素。
  • Jon Skeet,我原以为生成的数组列表中没有以字母开头的元素。

标签: java csv arraylist


【解决方案1】:

这就是正在发生的事情。

列表是Tmt1, Tmt2, Tmt3, ...。一开始,元素0是Tmt1

我们考虑将其移除;它以字母开头;所以我们删除它,然后移动到元素 1(第二个)。 但是到那时我们已经删除了一个,所以列表 OS 现在是 Tmt2, Tmt3, ...,我们正在考虑列表中的第二个,即 Tmt3Tmt2 永远不会被关注,因为它在您的列表向前移动的同时向后移动。

处理这个问题的最好方法是 Java 8 流 API,它允许您在列表上指定一个过滤器,并让它自动删除所有不符合过滤器要求的元素。它简洁易读,比 for 循环容易得多。

【讨论】:

    【解决方案2】:

    问题是您正在使用索引来删除元素。

    当您删除一个元素时,您的i 将关闭,第一次删除后您将不会删除正确的元素。

    假设您的 i5 并且您已经删除了该元素,在下一次迭代中,当 i6 时,当您执行 al1.get(i) 时,您实际上会在原始列表中获得 7th 元素,而不是第 6 个,因为您的第 6 个元素索引现在是 5 而不是 6。因此,您将根本无法访问该元素。

    您的for(int i=0;i&lt;al1.size();i++) 也不正确,因为您正在递增i 并减小al1 的大小。

    在最坏的情况下(when all the elements in the list starts with '-'),您将只能遍历一半的元素。

    更安全的方法是使用迭代器。

    Iterator<> it = al1.iterator();
    while(it.hasNext()){
         temp = it.next();  
         if (temp.charAt(0)=='-'|| (Character.isDigit(temp.charAt(0))==false))
           {
               it.remove();    
           }  
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用内置的removeif 方法:

      al1.removeIf(new Predicate<String>() {
      
                  @Override
                  public boolean test(String t) {
                       if (t.charAt(0)=='-'|| (Character.isDigit(t.charAt(0))==false)){
                             return true;
                      }
                      return false;
                  }
              });
      

      【讨论】:

      • removeIf() 只存在于 Java 8 之后。那么为什么不使用 lambda 而不是匿名类呢? al1.removeIf(t -&gt; t.charAt(0)=='-'|| !Character.isDigit(t.charAt(0)));。每次有if (condition) return true; else return false;,都可以写return condition;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      • 2011-02-13
      相关资源
      最近更新 更多