在Java中检查ArrayList元素(从csv文件中提取)并使用所需逻辑解析它们时出错

问题描述:

我读取了一个CSV文件,其格式如下所示。在Java中检查ArrayList元素(从csv文件中提取)并使用所需逻辑解析它们时出错

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

后来,我解析了csv文件,并将它的所有元素都带入了一个String的ArrayList。 现在该ArrayList看起来像

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

现在,我想删除其与字母开始字符串的ArrayList(如上所示)的所有元素。我使用下面的代码来做到这一点。 (AL1是我上面提到的ArrayList和温度是我使用检查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] 

(这不是我预期)

请帮助..谢谢

+3

好* *没有你所期望的,为什么?你是否已经通过调试器了解了这一点,并找出了出错的地方?您是否确定问题是使用列表还是使用字符串处理?有一件事要记住:如果你从你的列表中删除一个项目,所有其他的东西都洗牌......所以你想检查的下一个项目将有*相同的*索引作为你刚刚删除的。你可以在'remove'调用之后加入'i - '来解决这个问题。或者您可以从列表的* *端*开始。 –

+0

或者你可以创建另一个只包含你想要保留的元素的列表。 –

+0

乔恩Skeet,我期待由此产生的数组列表中没有字母开头的元素。 –

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

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

说你的i5和您已删除该元素,在下一次迭代时i6,当你做al1.get(i)你实际上在最初的名单得到7th元素,而不是第6因为你的第六元素索引现在是5但不是6。所以你根本无法访问那个元素。

您的for(int i=0;i<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();  
     } 
} 
+0

非常感谢... !!!它工作:) –

这是发生了什么事。

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

我们认为这是一个拆除;它以一封信开头;所以我们删除它,然后移动到元素1(第二个)。 但是到那时我们已经删除了一个,所以列表的操作系统现在为Tmt2, Tmt3, ...,我们正在考虑列表中的第二个,即Tmt3Tmt2永远不会被看到,因为它会在您的列表向前冲洗的同时向后移动。

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

,您可以使用内置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; 
      } 
     }); 
+2

removeIf()只存在于Java 8以后。那么为什么不使用lambda而不是匿名类呢? 'al1.removeIf(t - > t.charAt(0)==' - '||!Character.isDigit(t.charAt(0)));'。每次你有'if(condition)'返回true;否则返回false;',你可以写它'return condition;' –

+0

是的你是对的@JBNizet – Rustam