Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot add element to ObservableList (UnsupportedOperationException) in JavaFX [duplicate]

Initial Starting Point

I have an existing List of 1000 Person objects which I would like to insert an Extractor to listen for property changes within any Person objects (this ObservableList will be later attached to a TableView).

So my code would be like:

ObservableList<Person> observablePersons = FXCollections.observableList(personlist,
    personextractor);

Error Message

But when I try to add a new person objects to this ObservableList observablePersons, I run into this error:

run:
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at com.sun.javafx.collections.ObservableListWrapper.doAdd(ObservableListWrapper.java:101)
    at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:151)
    at java.util.AbstractList.add(AbstractList.java:108)
    at test.listchangelistener.listChangeDemo.main(listChangeDemo.java:72)
Java Result: 1

Could you please tell me why would I come across this error message? My java version is jdk1.8.0_91 (32-Bit)

Person Class

package test.listchangelistener;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

class Person {

    private final IntegerProperty age = new SimpleIntegerProperty();
    private final StringProperty name = new SimpleStringProperty();

    public Person(String name, Integer age) {
        setName(name);
        setAge(age);
    }

    public int getAge() {
        return age.get();
    }

    public final void setAge(int value) {
        age.set(value);
    }

    public IntegerProperty ageProperty() {
        return age;
    }

    public String getName() {
        return name.get();
    }

    public final void setName(String value) {
        name.set(value);
    }

    public StringProperty nameProperty() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" + "age=" + age.get() + ", name=" + name.get() + '}';
    }

}

Test Code

package test.listchangelistener;

import java.util.Arrays;
import java.util.List;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.util.Callback;


public class listChangeDemo {
    public static void main(String[] args) {

        Person p1 = new Person("Ted", 26);
        Person p2 = new Person("Anne", 19);

        // just a simple list
        List<Person> persons = Arrays.asList(p1, p2);

        // extractor to observe change of person properties
        Callback<Person, Observable[]> extractor = (Person p) -> {
            return new Observable[]{
                p.ageProperty(),
                p.nameProperty()
            };
        };

        // make list observable and attach extractor
        ObservableList<Person> observablePersons = FXCollections.observableList(persons, extractor);

        // create listchangeListener for observableList
        ListChangeListener listener = (ListChangeListener) (ListChangeListener.Change c) -> {
            while (c.next()) {
                if (c.wasAdded()) {
                    System.out.println("these were added: ");

                    List addedSubList = c.getAddedSubList();
                    addedSubList.forEach((Object t) -> {
                        System.out.println("added Person: " + t);
                    });
                } else if (c.wasRemoved()) {
                    System.out.println("these were removed");

                    List removedSubList = c.getRemoved();
                    removedSubList.forEach((Object t) -> {
                        System.out.println("removed Person: " + t);
                    });

                } else if (c.wasUpdated()) {
                    System.out.println("these were updated");

                    System.out.println("Updated elements are: "
                            + c.getList().subList(c.getFrom(), c.getTo()));
                }
            }
        };

        // attach listchangeListener to observableList
        observablePersons.addListener(listener);

        // testing changes
        observablePersons.add(new Person("Siegfried", 10));

    }
}
like image 225
Chiggiddi Avatar asked Jul 04 '16 11:07

Chiggiddi


1 Answers

The problem is coming from the creation of your backing List:

List<Person> persons = Arrays.asList(p1, p2);

If you take a look on the javadoc of Arrays.asList:

Returns a fixed-size list backed by the specified array.

On a closer look you got an UnsupportedOperationException because List.add() is an optional operation:

Throws: UnsupportedOperationException - if the add operation is not supported by this list.

You can update the creation of the backing list as:

List<Person> persons = new ArrayList<Person>(Arrays.asList(p1, p2));

The difference is that the returned ArrayList is an exact, independent copy of the passed one, therefore the restriction described above is not valid anymore in this case.

You can also take a look on this question which explaines this topic in depths:

Difference between Arrays.asList(array) vs new ArrayList<Integer>(Arrays.asList(ia)) in java

like image 69
DVarga Avatar answered Nov 13 '22 15:11

DVarga