Java List.add () UnsupportedOperationException

225

Saya mencoba menambahkan objek ke sebuah List<String>instance tetapi ia melempar UnsupportedOperationException. Adakah yang tahu mengapa?

Kode Java saya:

String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);

for (String member : membersList) {
    Person person = Dao.findByName(member);
    List<String> seeAlso;
    seeAlso = person.getSeeAlso();
    if (!seeAlso.contains(groupDn)){
        seeAlso.add(groupDn);
        person.setSeeAlso(seeAlso);
    }
}

Pesan kesalahan:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add (Sumber Tidak Dikenal)
    java.util.AbstractList.add (Sumber Tidak Dikenal)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)
FAjir
sumber

Jawaban:

457

Tidak setiap Listimplementasi mendukung add()metode ini.

Salah satu contoh umum adalah Listdikembalikan oleh Arrays.asList(): didokumentasikan tidak mendukung modifikasi struktural (yaitu menghapus atau menambahkan elemen) (tambang penekanan):

Mengembalikan daftar ukuran tetap yang didukung oleh array yang ditentukan.

Bahkan jika itu bukan spesifik yang ListAnda coba modifikasi, jawabannya tetap berlaku untuk Listimplementasi lain yang tidak dapat diubah atau hanya mengizinkan beberapa perubahan yang dipilih.

Anda dapat mengetahuinya dengan membaca dokumentasi UnsupportedOperationExceptiondan List.add(), yang mendokumentasikan ini sebagai "(operasi opsional)". Arti yang tepat dari frasa ini dijelaskan di bagian atas Listdokumentasi.

Sebagai solusinya, Anda dapat membuat salinan daftar ke implementasi yang dikenal dapat dimodifikasi seperti ArrayList:

seeAlso = new ArrayList<>(seeAlso);
Joachim Sauer
sumber
1
jadi saya harus menggunakan daftar contoh untuk menguji apakah mengandung elemen saya dan contoh array ketika saya harus menambahkan elemen? itu menulis?
FAjir
90
@Florito: Ini akan berhasil: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre
atau mungkin saya harus melemparkan objek Daftar saya ke ArrayList atau yang lain?
FAjir
2
Tidak terlalu. Jika Anda ingin menambahkan elemen ke Listimplementasi yang tidak memungkinkan penambahan, maka Anda harus menyalinnya Listke implementasi yang tidak ( ArrayListadalah kandidat umum) dan menambahkannya.
Joachim Sauer
8

Banyak dari implementasi Daftar mendukung dukungan terbatas untuk menambah / menghapus, dan Arrays.asList (membersArray) adalah salah satunya. Anda perlu memasukkan catatan di java.util.ArrayList atau menggunakan pendekatan di bawah ini untuk mengubahnya menjadi ArrayList.

Dengan perubahan minimal pada kode Anda, Anda dapat melakukan di bawah ini untuk mengonversi daftar menjadi ArrayList. Solusi pertama adalah memiliki perubahan minimum dalam solusi Anda, tetapi yang kedua lebih dioptimalkan, saya kira.

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));

ATAU

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
krmanish007
sumber
4

Bentuk konsep Warisan, Jika beberapa metode pertikular tidak tersedia di kelas saat ini akan mencari metode itu di kelas super. Jika tersedia dijalankan.

Ini mengeksekusi metode AbstractList<E>kelas add()yang melempar UnsupportedOperationException.


Saat Anda mengonversi dari Array ke Obejct Collection. yaitu, berbasis array ke API berbasis koleksi maka ia akan memberi Anda objek koleksi ukuran tetap, karena perilaku Array adalah ukuran tetap.

java.util.Arrays.asList (T ... a)

Sampel souce untuk konformasi.

public class Arrays {
    public static <T> List<T> asList(T... a) {
        return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
    }
    //...
    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
        //...
    }
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...
    }

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }
    private class ListItr extends Itr implements ListIterator<E> {
        //...
    }
}

Bentuk Sumber di atas Anda dapat mengamati bahwa java.util.Arrays.ArrayListkelas tidak @Override add(index, element), set(index, element), remove(index). Jadi, Dari pewarisan itu menjalankan fungsi AbstractList<E>kelas super add()yang melempar UnsupportedOperationException.

Seperti AbstractList<E>kelas abstrak yang menyediakan implementasinya untuk iterator() and listIterator(). Jadi, kita bisa beralih ke objek daftar.

List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});

try {
    list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
    System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);

Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );

ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext())    System.out.println("Forward  iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());

Anda bahkan dapat membuat kelas Koleksi ukuran-bentuk array tetap Collections.unmodifiableList(list);

Sumber sampel:

public class Collections {
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }
}

A Collection- kadang-kadang disebut wadah - hanyalah sebuah objek yang mengelompokkan beberapa elemen menjadi satu unit. Koleksi digunakan untuk menyimpan, mengambil, memanipulasi, dan mengkomunikasikan data agregat.

@Lihat juga

Yash
sumber
3

Anda harus menginisialisasi Daftar Anda, lihat juga:

List<String> seeAlso = new Vector<String>();

atau

List<String> seeAlso = new ArrayList<String>();
dwayne
sumber
2
Variabel tidak diinisialisasi tidak akan menyebabkan UnsupportedOperationExceptiondalam add(). Anda akan mendapatkan NPE sebagai gantinya.
Stephen C
0

Daftar membersList = Arrays.asList (membersArray);

mengembalikan daftar yang tidak dapat diubah, yang perlu Anda lakukan adalah

ArrayList baru <> (Arrays.asList (membersArray)); untuk membuatnya bisa berubah

Ziv.Ti
sumber
Ini bukan daftar abadi. Operasi mutasi yang tidak mengubah panjang daftar didukung / akan berfungsi. Kuncinya adalah bahwa panjang daftar tidak dapat berubah karena daftar didukung oleh array ... yang panjangnya tidak dapat berubah.
Stephen C
-1

alih-alih menggunakan add () kita bisa menggunakan addall ()

{ seeAlso.addall(groupDn); }

add menambahkan satu item, sementara addAll menambahkan setiap item dari koleksi satu per satu. Pada akhirnya, kedua metode mengembalikan true jika koleksi telah dimodifikasi. Dalam kasus ArrayList hal ini sepele, karena koleksi selalu dimodifikasi, tetapi koleksi lain, seperti Set, dapat mengembalikan false jika item yang ditambahkan sudah ada di sana.

Allen
sumber
-3

Anda tidak dapat mengubah hasil dari kueri LDAP. Masalah Anda ada di baris ini:

seeAlso.add(groupDn);

Daftar seeAlso tidak dapat dimodifikasi.

neknik
sumber
1
masalahnya bukan karena itu tetapi seperti yang Joachim tunjukkan di atas terkait dengan implementasi Daftar yang mungkin tidak mendukung add ().
Liv