简体   繁体   中英

Encountered in Java 8 - JDK-8023339 : j.u.Arrays.asList().removeIf() is “lazy” in throwing java.lang.UnsupportedOperationException

First time with Java 8 and I encountered this bug . Anyone encountered this too? Bug is marked as resolved however I'm not sure why I'm getting it. I also excuted the listed sample code in the bug and did get UOE. Here's my environment:

OS in VM x64

$ cat /etc/lsb-release
DISTRIB_ID="elementary OS"
DISTRIB_RELEASE=0.2.1
DISTRIB_CODENAME=luna
DISTRIB_DESCRIPTION="elementary OS Luna"

JDK

$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
$ javac -version
javac 1.8.0_25

Here's my test

package test;

import org.junit.Test;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

public class RemoveIfTest {
    static interface I {
        // i want to remove this
        public void a();

        public String b();
    }

    @Test(expected = UnsupportedOperationException.class)
    public void test() {
        List<Method> methods = Arrays.asList(I.class.getMethods());

        // what we have
        methods.forEach(m -> System.out.println(m));
        // output: public abstract void test.RemoveIfTest$I.a()
        //         public abstract java.lang.String test.RemoveIfTest$I.b()

        // old way
        for (Method method : methods) {
            if (method.getReturnType().equals(Void.TYPE)) {
                System.out.println("Remove this > " + method);
            }
        }
        // output: Remove this > public abstract void test.RemoveIfTest$I.a()

        // got UOE
        methods.removeIf(m -> m.getReturnType().equals(Void.TYPE));
    }
}

And here's a screenshot of the evaluated line 调试时

The highlighted line is where it died 调试时

As the Javadoc for Arrays.asList states it is a fixed size list backed by the array:

Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray. The returned list is serializable and implements RandomAccess.

Looking at the source for java.util.Arrays , it returns its own implementation of a List which is similar to the java.util.ArrayList .

private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable
{
    ...
}

It does not override the remove method from AbstractList , which you can see from the source that it throws this exception.

public E remove(int index) {
    throw new UnsupportedOperationException();
}

The solution (like stated already) is to use a list that supports removal.

List<Method> methods = new ArrayList<>(Arrays.asList(I.class.getMethods()))

Answer from @JBNizet. Thank you.

From

// List methods = java.util.Arrays.ArrayList
List<Method> methods = Arrays.asList(I.class.getMethods())

To

 // List methods = java.util.ArrayList
 List<Method> methods = new ArrayList<>(Arrays.asList(I.class.getMethods()));

you should check your list,the jdk1.8 describe the throws,the throws's description is "UnsupportedOperationException if elements cannot be removed from this collection. Implementations may throw this exception if a matching element cannot be removed or if, in general, removal is not supported." I test this list, it's work. this list is as follows:

List<String> list=new ArrayList<String>();
    list.add("1");
    list.add("2");
    list.removeIf(s->s.equals("1"));

so,good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM