我们知道,Java 的两个集合取交集操作使用的是 retainAll() 方法,然而我在取交集时却遇到了 UnsupportedOperationException 异常,是怎么回事呢?
代码是这样的:
- @SpringBootTest
- class SpringbootStudyApplicationTests {
- @Test
- void test0730(){
- String [] arr = {"1111","2222","3333","4444","5555"};
- List
listA = Arrays.asList(arr); - List
listB = new ArrayList<>(); - listB.add("1111");
- listB.add("3333");
- // listA对listB取交集
- listA.retainAll(listB);
- System.out.println(listA);
- }
- }
运行之后,报出以下异常:
按照打印的异常信息,找到 AbstractCollection.retainAll() 方法,源码如下:
- public boolean retainAll(Collection> c) {
- Objects.requireNonNull(c);
- boolean modified = false;
- Iterator
it = iterator(); - while (it.hasNext()) {
- if (!c.contains(it.next())) {
- it.remove();
- modified = true;
- }
- }
- return modified;
- }
-
- default void remove() {
- throw new UnsupportedOperationException("remove");
- }
请注意,该方法上有一段注释说明:Note that this implementation will throw an UnsupportedOperationException if the iterator returned by the iterator method does not implement the remove method and this collection contains one or more elements not present in the specified collection. 也就是说,iterator() 方法返回的迭代器未实现 remove() 方法,并且此集合包含指定集合中不存在的一个或多个元素,则此实现将引发 UnsupportedOperationException 异常。
到这里似乎明白了什么,迭代器未实现 remove() 方法?那需要继续看下 Arrays.asList() :
- public static
List asList(T... a) { - return new ArrayList<>(a);
- }
额,Arrays 的内部类 ArrayList 集合确实没有 remove() 方法,也没有 retainAll() 方法,如下:
那么问题来了,为什么使用 new ArrayList(); 的 ArrayList 集合却没问题呢?打开 ArrayList 集合源码看一眼也就明白了:
至此,这个问题的原因就找到了。为了避免这种坑,我们应该正确使用 List 集合,把开始的代码改造成这样就没问题了:
- @SpringBootTest
- class SpringbootStudyApplicationTests {
- @Test
- void test0730(){
- String [] arr = {"1111","2222","3333","4444","5555"};
- List
listA = new ArrayList<>(Arrays.asList(arr)); - List
listB = new ArrayList<>(); - listB.add("1111");
- listB.add("3333");
- // listA对listB取交集
- listA.retainAll(listB);
- System.out.println(listA);
- }
- }
在此记录一下~