【问题标题】:Removing certain values from an arraylist从数组列表中删除某些值
【发布时间】:2014-03-05 21:20:41
【问题描述】:

我有一个 csv 文件中的数字列表,已导出到 ArrayList。现在,问题是我的 ArrayList 是 String 而不是 double。我试过使用

ArrayList<Double> arr = new ArrayList<Double>();`

但它给了我一个错误。

我想删除 ArrayList 中小于 0.1 的任何数字。这是我的代码:

public class Example1
{
public static void main(String[] args) throws InvalidFormatException, IOException{
    ArrayList arr=new ArrayList();
File f=new File("C:\\java\\marchcalllast.csv");
Scanner in=new Scanner(f).useDelimiter(",");

while(in.hasNext())
{    
arr.add(in.next());
}


for (int i = 0; i < arr.size(); i++){
  Double item = Double.valueOf(arr.get(i));
  if (item < 0.1) {
    arr.remove(i);
  }
}
System.out.println(arr);

它给了我以下错误:

错误:没有找到适合 valueOf(java.lang.Object) 的方法 方法 java.lang.Double.valueOf(double) 不适用 (实参java.lang.Object不能通过方法调用转换为double) 方法 java.lang.Double.valueOf(java.lang.String) 不适用 (实参java.lang.Object无法通过方法调用转换为java.lang.String)

【问题讨论】:

  • 不要使用原始类型。
  • 另外,最好在将其添加到列表之前检查您的 while 双精度值。
  • Excel 内置了非常易于使用的过滤器。

标签: java csv arraylist


【解决方案1】:

如果您使用泛型,您的 IDE 会报错,您可以很容易地看到问题所在。当您尝试将元素从 String 解析为 Double 时,编译器实际上将它们视为 Object(即使它们实际上是 String),您在这里错过了一次强制转换。

这是第一个修复:

public static void main(String[] args) throws IOException {
    List<Double> arr = new ArrayList<Double>();
    File f = new File("C:\\java\\marchcalllast.csv");
    Scanner in = new Scanner(f).useDelimiter(",");

    while (in.hasNext()) {
        arr.add(Double.valueOf(in.next()));
    }

    for (Double item : arr) {
        if (item < 0.1) {
            arr.remove(item); // This is not allowed here, you are iterating on arr
        }
    }

    System.out.println(arr);
}

现在,还有一个错误:您无法在迭代集合时从集合中删除元素。为了解决这个问题,例如,您可以使用第二个临时集合:

public static void main(String[] args) throws IOException {
    List<Double> arr = new ArrayList<Double>();
    File f = new File("C:\\java\\marchcalllast.csv");
    Scanner in = new Scanner(f).useDelimiter(",");

    while (in.hasNext()) {
        arr.add(Double.valueOf(in.next()));
    }

    List<Double> toRemove = new ArrayList<Double>();
    for (Double item : arr) {
        if (item < 0.1) {
            toRemove.add(item);
        }
    }
    arr.removeAll(toRemove);

    System.out.println(arr);
}

【讨论】:

    【解决方案2】:

    您不需要使用.valueOf() 获取值。您只需要编写Double item = arr.get(i); 即可获取该索引处的值并继续执行 if 语句。

    【讨论】:

    • 这给了我一个错误:不兼容的类型,需要:java.lang.Double,找到:java.lang.Object
    【解决方案3】:
    Double double = Double.parseDouble(arr.get(i));
    

    【讨论】:

      【解决方案4】:

      您可以将第二个循环滚动到 CSV 解析阶段。如果您知道输入应该是数字,则可以使用异常处理忽略非数字输入。

      这是一个例子:

      public static void main(String[] args) throws InvalidFormatException, IOException{
        List arr=new ArrayList();
          File f=new File("C:\\java\\marchcalllast.csv");
          Scanner in=new Scanner(f).useDelimiter(",");
      
          while(in.hasNext()){
              String nextToken = in.next();
              try{
                  Double tokenAsNumber = Double.parseDouble(nextToken);
      
                  if(tokenAsNumber >= 0.1){
                      arr.add(tokenAsNumber);
                  }
                  else{
                      System.out.println("Ignoring value less than 0.1: "+tokenAsNumber);
                  }       
              }
              catch(NumberFormatException nfe){
                  System.err.println(nextToken + " is not a number, ignoring");
              }   
          }
      
          System.out.println(arr);
      }
      

      尽早转换是很好的做法:)

      【讨论】:

        【解决方案5】:

        您的 ArrayList 没有指定它包含的类型。所以它被视为只包含“对象”。因此,即使您向其中添加字符串,当您执行“获取”时,它仍会返回对象。但是 Double.valueOf 想要解析字符串,而不是对象。 所以演员表会起作用:

        Double item = Double.valueOf((String) arr.get(i));
        

        但是,您可以使用泛型来指定 ArrayList 将保存的项目类型:

        List<String> arr=new ArrayList<String>();
        

        现在,你不需要那个演员表了,因为“get”会返回字符串。

        【讨论】:

          【解决方案6】:

          为什么在读取时过滤时创建一个新列表或过滤/修改一个:

          public class FilterDouble {
          
          public static void main(String[] args) throws IOException {
              File file = new File("C:\\java\\marchcalllast.csv");
              Scanner in = new Scanner(file).useDelimiter(",");
          
              List<Double> list = new ArrayList<>();
              while (in.hasNext()) {
                  final double value = Double.parseDouble(in.next());
                  if (value >= 0.1) {
                      list.add(value);
                  }
              }
              System.out.println(list);
          }
          

          如果你真的想从列表中删除项目,我会使用迭代器删除方法:

          for (Iterator<Double> iterator = arr.iterator(); iterator.hasNext(); ) {
               Double next = iterator.next();
               if (next < 0.1) {
                   iterator.remove();
               }
          }
          

          或者最好等到 Java 8 发布(几个小时后),然后使用新的功能性 api 过滤集合,使原始集合保持不变。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-09-04
            • 2019-01-07
            • 1970-01-01
            • 2015-04-04
            • 1970-01-01
            • 2012-11-13
            • 1970-01-01
            相关资源
            最近更新 更多