java.util.Arrays.asList与removeIf一起使用会抛出UnsupportedOperationException异常。

29

我正在为接下来的两个月准备OCPJP 8考试,目前我对其中一个问题感到困惑,因为我不理解它的原因。

public class BiPredicateTest {
    public static void main(String[] args) {
        BiPredicate<List<Integer>, Integer> containsInt = List::contains;
        List<Integer> ints = java.util.Arrays.asList(1,20,20);
        ints.add(1);
        ints.add(20);
        ints.add(20);
        System.out.println(containsInt.test(ints, 20));
        
        BiConsumer<List<Integer>, Integer> listInt = BiPredicateTest::consumeMe;
        listInt.accept(ints, 15);
        
    }
    
    public static void consumeMe(List<Integer> ints, int num) {
        ints.removeIf(i -> i>num);
        ints.forEach(System.out::println);
    }
}

这段代码显然是可以编译通过的!但是当你运行它时,你会看到如下异常:

C:\Users\user\Documents>javac BiPredicateTest.java

C:\Users\user\Documents>java BiPredicateTest
true
Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractList.remove(AbstractList.java:161)
        at java.util.AbstractList$Itr.remove(AbstractList.java:374)
        at java.util.Collection.removeIf(Collection.java:415)
        at BiPredicateTest.consumeMe(BiPredicateTest.java:22)
        at BiPredicateTest.main(BiPredicateTest.java:17)

我需要一些帮助来理解为什么asList方法与removeIf无法正常工作?我认为它会返回一个实现removeIf方法的ArrayList实例!
感谢任何回答。
更新:2022年4月16日 即使使用java.util.Arrays.asList,错误也不再发生,我注意到:
  • 最新的Java 1.8 *实现不再使用内部的ArrayList类,而是使用java.util包下的类。
  • List接口现在也有默认实现。

2
"我假设它会返回一个ArrayList实例"。为什么你要做出这样的假设呢?当你计划学习Java证书时,你应该学会阅读文档。所以不要“假设”什么,要去阅读文档并且“理解”。 - Tom
@Tom 谢谢你提醒,你说得完全正确。但是当其他人确切知道答案时,我会感到更加舒适,这可以为我的阅读增加验证。:) 无论如何还是谢谢你 :) - mark ortiz
答案并不直接在文档中。有时我们需要一些帮助来解决代码或流程方法中的问题。感谢你的问题,马克。 - Guilherme
1个回答

58

java.util.Arrays.asList() 会生成一个列表,其中无法移除元素,因此在尝试移除时会抛出异常。

您可以使用 ArrayList 进行包装:

List<Integer> ints = new java.util.ArrayList<>(java.util.Arrays.asList(1,20,20));

更新

Arrays.asList() 返回 return new ArrayList<>(a);,其中 ArrayList 不是 java.util.ArrayList,而是 java.util.Arrays.ArrayList (内部类),它不允许移除。


也许你应该说它不是不能与removeIf一起使用,而是与add一起使用。 - Kedar Mhaswade
8
Arrays.asList() 返回的列表不是不可修改的,它具有固定的长度,因此您无法删除或添加项目,但可以更改值! - Mark Rotteveel
你是对的,答案不够准确。已经修正为表明所生成的列表不允许删除。 - Roman Puchkovskiy
哦!!!谢谢@rpuch,我以为由asList方法返回的ArrayList与java.util下的相同包一样,但实际上它返回了java.util.Arrays类下的ArrayList。干杯!! :) - mark ortiz
我在单元测试中使用了Arrays.asList。但是在真正的代码中出现了错误。而且这个方法是公共的。无意中我发现我需要获取一个不可变列表,如果是这样就没有错误了。 - Guilherme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接