remove () na lista criada por Arrays.asList () lança UnsupportedOperationException

91

Eu tenho uma coleção c1<MyClass>e uma matriz a<MyClass>. Estou tentando converter a matriz em uma coleção c2e fazer c1.removeAll(c2), mas isso joga UnsupportedOperationException. Descobri que a asList()classe de Arrays retorna Arrays.ArrayListclasse e esta classe herda a removeAll()de AbstractList()cuja implementação é gerada UnsupportedOperationException.

    Myclass la[] = getMyClass();
    Collection c = Arrays.asList(la);
    c.removeAll(thisAllreadyExistingMyClass);

Existe alguma maneira de remover os elementos? por favor ajude

javalearner
fonte
Pergunta relacionada: stackoverflow.com/questions/2965747/…
Ram

Respostas:

170

Arrays.asListretorna um Listwrapper em torno de uma matriz. Este wrapper tem um tamanho fixo e é apoiado diretamente pelo array e, como tal, chamadas a setmodificarão o array e qualquer outro método que modifique a lista lançará um UnsupportedOperationException.

Para corrigir isso, você deve criar uma nova lista modificável copiando o conteúdo da lista de wrapper. Isso é fácil de fazer usando o ArrayListconstrutor que leva um Collection:

Collection c = new ArrayList(Arrays.asList(la));
Etienne de Martel
fonte
1
Eu estava olhando o código-fonte para o java.util.Arrays asList()método e parece retornar um ArrayList. No entanto, quando faço um System.out.println(list.getClass());, recebo class java.util.Arrays$ArrayList. Portanto, ele usa a ArrayListclasse interna , que não tem um método addou remove. Só estou me perguntando qual é o sentido de ter uma ArrayListclasse interna em vez de usar java.util.ArrayListuma e por que não ter um método add()e remove()?
Abdul
Correção ao meu comentário acima: ele tem um método adderemove
Abdul
1
@Abdul Porque não existe um tamanho fixo java.util.ArrayList. Você deseja que uma implementação de Listque lance uma exceção se fizer algo ilegal com ela (como adicionar ou remover) e ArrayListnão atender a esse requisito.
Etienne de Martel de
@Abdul Arrays.asListapenas cria um wrapper List. Mas ainda é um java.util.List, então deve ter esses métodos. Mas eles não podem ser aplicados porque isso levaria à criação de uma nova matriz com tamanho diferente. O que não pode ser feito porque as modificações que você ainda pode fazer podem ser feitas por meio da lista retornada e da matriz original. Isso não será possível se a lista retornada puder ser alterada de forma que basicamente jogue fora a referência do array original.
Adam Hošek
13

Sim, Arrays.asList(..)é uma coleção que não pode ser expandida ou reduzida (porque é apoiada pela matriz original e não pode ser redimensionada).

Se você deseja remover elementos, crie um new ArrayList(Arrays.asList(..)ou remova elementos diretamente da matriz (isso será menos eficiente e mais difícil de escrever)

Bozho
fonte
+1 Esta resposta é a única correta: Arrays.asList () retorna uma lista não modificável - é o que está lançando a exceção. Não tem nada a ver com ser "apoiado por um array" etc ... todos os ArrayLists são apoiados por arrays - grande coisa.
Boêmio
1
Mas se você ler mais nos documentos, perceberá que não é realmente inalterável ... "Retorna uma lista de tamanho fixo apoiada pela matriz especificada. (Mudanças na lista retornada" gravam "na matriz .) "-1, Etienne tem toda a razão.
Steven Schlansker
1
@Steven Sim, é por isso que diz "tamanho fixo" em vez de "não modificável" ou "somente leitura". Na verdade, irei editar minha resposta agora para refletir isso.
Etienne de Martel,
1
@Bohemian, As coleções retornadas são de fato 'modificáveis' porque é possível chamar o método 'set'.
javalearner
2
Se você for escolher nits como esse, também pode dizer coisas insípidas como "ele lança UnsupportedOperationException porque há uma instrução throw UnsupportedOperationException no código". Os consumidores de uma API não se importam com qual superclasse AbstractBlah está lançando uma exceção, eles se importam com quais são os contratos e expectativas da classe que usam. Na JVM v + 1, é inteiramente possível que a biblioteca de classes mude onde a exceção é lançada - mas o contrato não mudará.
Steven Schlansker,
7

É assim que Array.asList()funciona, porque é apoiado diretamente pelo array. Para obter uma lista totalmente modificável, você teria que clonar a coleção em uma coleção criada por você mesmo.

Collection c = new ArrayList(Arrays.asList(la))
Henko
fonte
1
A lista é modificável, mas apenas por meio de set (). a coleção retornada é de tamanho fixo.
javalearner
Na verdade, nunca disse que não era modificável. Apenas isso, para obter uma lista (totalmente) modificável, você teria que usar um ArrayList. A diferença talvez não fosse muito clara. :-) Se a lista é modificável ou não é uma questão de definição, é "semimodificável" mas não totalmente modificável na minha opinião.
henko