如何从Java ArrayList中删除元素

时间:2020-01-09 10:35:01  来源:igfitidea点击:

如果需要用Java从ArrayList中删除元素,则有3个选项。

  • 使用ArrayList类的remove()方法删除元素。参见示例。
  • 使用ArrayList返回的迭代器的remove()方法。参见示例。
  • 从Java 8开始使用removeIf()方法。参见示例。

使用ArrayList的remove方法删除元素

ArrayList类中的remove()方法有两种变体

  • remove(int index)–此方法删除此列表中指定索引处的元素。
  • boolean remove(Object o)-此方法从列表中删除第一次出现的指定元素(如果存在)。

这是一个通过传递元素本身(使用remove(Object o)方法)从Java中的ArrayList中删除元素的示例。

import java.util.List;
public class ListElementRemoval {
  public static void main(String[] args) {
    List<String> carList = new ArrayList<String>();
    carList.add("Audi");
    carList.add("BMW");
    carList.add("Jaguar");
    carList.add("BMW");
    carList.add("Mini Cooper");
    
    System.out.println("List elements- " + carList);
    // removing element
    carList.remove("Mini Cooper");        
    System.out.println("List elements after removal- " + carList);
  }
}

输出:

List elements- [Audi, BMW, Jaguar, BMW, Mini Cooper]
List elements after removal- [Audi, BMW, Jaguar, BMW]

使用迭代器的remove方法删除元素

如果要在迭代ArrayList时从ArrayList中删除元素,则应使用迭代器本身的remove()方法。这是必需的,因为除非通过迭代器自己的remove方法,否则不允许在创建迭代器后随时在结构上修改(添加或者删除元素)ArrayList,否则将引发ConcurrentModificationException。

让我们看一个例子,这里使用ArrayList类的remove方法在迭代List时删除了元素。

import java.util.Iterator;
import java.util.List;

public class ListElementRemoval {
  public static void main(String[] args) {
    List<String> carList = new ArrayList<String>();
    carList.add("Audi");
    carList.add("BMW");
    carList.add("Jaguar");
    carList.add("BMW");
    carList.add("Mini Cooper");    
    // getting iterator
    Iterator<String> itr = carList.iterator();
    while(itr.hasNext()){
      String car = itr.next();
      if(car.equals("Mini Cooper")) {
        // Using ArrayList's remove method
        carList.remove(car);
      }
    }
  }
}

输出:

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891)
	at com.theitroad.ListElementRemoval.main(ListElementRemoval.java:19)

这是更改后的代码,其中迭代器的remove方法用于从ArrayList中删除元素。

public class ListElementRemoval {
  public static void main(String[] args) {
    List<String> carList = new ArrayList<String>();
    carList.add("Audi");
    carList.add("BMW");
    carList.add("Jaguar");
    carList.add("BMW");
    carList.add("Mini Cooper");    
    System.out.println("List elements- " + carList);
    // getting iterator
    Iterator<String> itr = carList.iterator();
    while(itr.hasNext()){
      String car = itr.next();
      if(car.equals("Mini Cooper")) {
        itr.remove();
      }
    }
    System.out.println("List elements after removal- " + carList);
  }
}

输出:

List elements- [Audi, BMW, Jaguar, BMW, Mini Cooper]
List elements after removal- [Audi, BMW, Jaguar, BMW]

如我们所见,现在不会引发ConcurrentModificationException。

使用removeIf方法删除元素

从Java 8开始,我们还可以使用removeIf()方法从ArrayList中删除元素,该数组以Predicate作为参数,并删除所有满足给定Predicate的元素。
谓词是Java 8中添加的功能接口。

public class ListElementRemoval {
  public static void main(String[] args) {
    List<String> carList = new ArrayList<String>();
    carList.add("Audi");
    carList.add("BMW");
    carList.add("Jaguar");
    carList.add("BMW");
    carList.add("Mini Cooper");    
    System.out.println("List elements- " + carList);
    
    carList.removeIf(c -> c.equalsIgnoreCase("Mini Cooper"));
    
    System.out.println("List elements after removal- " + carList);
  }
}

remove()方法的自动装箱问题

由于ArrayList中的remove()方法具有很多变体,我们可以在其中传递索引或者要删除的对象。如果元素由于自动装箱而包装到其对应的包装器类,则这些重载的方法可能会引起问题。

让我们尝试以一个具有ArrayList of Integers的示例来阐明它。

public class ListElementRemoval {
  public static void main(String[] args) {
    List<String> carList = new ArrayList<String>();
    carList.add("Audi");
    carList.add("BMW");
    carList.add("Jaguar");
    carList.add("BMW");
    carList.add("Mini Cooper");    
    System.out.println("List elements- " + carList);
    
    carList.removeIf(c -> c.equalsIgnoreCase("Mini Cooper"));
    
    System.out.println("List elements after removal- " + carList);
  }
}

在这里,我们要传递要从ArrayList中删除的Integer对象6,但是将使用带有int参数作为参数的remove()方法。在这种情况下,不会进行自动装箱,并且会出现错误。

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 6 out-of-bounds for length 4
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.remove(ArrayList.java:517)
	at com.theitroad.ListElementRemoval.main(ListElementRemoval.java:16)

如果存在此类歧义,则应传递对象本身以进行删除。

public static void main(String[] args) {
    List<Integer> numebrList = new ArrayList<Integer>();
    numebrList.add(3);
    numebrList.add(4);
    numebrList.add(5);
    numebrList.add(6);
    System.out.println("List elements- " + numebrList);
    // Passing object explicitly 
    numebrList.remove(Integer.valueOf(6));

    System.out.println("List elements after removal- " + numebrList);
  }
}