user188097
user188097

Reputation:

Equivalent of C# ObservableCollection in Java

I was wondering if there is a data structure that acts like an OberservableCollection almost like in C# that is able to take a certain type.

ex:

In C# i am able to say..

 ObservableCollection<Beer> Beer = new ObservableCollection<Beer>();
 Beer.add("Bud"); <br>
 Beer.add("Coors");

Assuming that the class Beer is made and we can change the alcohol content so that

 Beer[1].content = 5;

I was wondering if anyone knows if there is such a data structure/s that work as well with Java.


I am a C# programmer, not much of a Java programmer so just wondering. Also, it has to be able to take in a custom type, not generic.

Upvotes: 12

Views: 10254

Answers (7)

magicsign
magicsign

Reputation: 97

You can consider using the java.util.Observable class, here is an example :

public class Try extends Observable{

  private static List<String> list = new ArrayList<String>();
  private static Try observableObj = new Try();

  public static List<String> getList(){
    observableObj.setChanged();
    observableObj.notifyObservers();
    return list;
  }


  public static void main(String[] args) throws RemoteException {

    Try2 observer1 = new Try2();
    Try2 observer2 = new Try2();
    observableObj.addObserver(observer1);
    observableObj.addObserver(observer2);

    System.out.println(getList().isEmpty());

  }
}

class Try2 implements Observer{

  @Override
  public void update(Observable arg0, Object arg1) {
    System.out.println(this.toString()+" has been notified");

  }
}

In this way every time the ArrayList gets accessed the two observers get notified.

Upvotes: 0

jewelsea
jewelsea

Reputation: 159536

Observable data structures (ObservableList, ObservableMap, etc) are included in Oracle Java 7u6+ as part of the JavaFX project. A corresponding library for OpenJDK is provided by the OpenJFX project.

Here is a tutorial on using JavaFX collections.

And some sample code for using a JavaFX observable list from the linked tutorial:

import java.util.List;
import java.util.ArrayList;
import javafx.collections.*;

public class CollectionsDemo {
  public static void main(String[] args) {
    // Use Java Collections to create the List.
    List<String> list = new ArrayList<String>();

    // Now add observability by wrapping it with ObservableList.
    ObservableList<String> observableList = FXCollections.observableList(list);
    observableList.addListener(new ListChangeListener() {
      @Override public void onChanged(ListChangeListener.Change change) {
        System.out.println("Detected a change! ");
      }
    });

    // Changes to the observableList WILL be reported.
    // This line will print out "Detected a change!"
    observableList.add("item one");

    // Changes to the underlying list will NOT be reported
    // Nothing will be printed as a result of the next line.
    list.add("item two");

    System.out.println("Size: "+observableList.size());
  }
}

Upvotes: 3

bennyl
bennyl

Reputation: 2956

JavaFX now has ObservableList that match your needs, in the case that you don't want to depend on JavaFX - here is a class that I wrote a while ago that can be used instead.

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 *
 * @author bennyl
 */
public class ObservableList<T> implements List<T> {

    private List<T> wrapped;
    private LinkedList<Listener<T>> listeners = new LinkedList<>();

    public ObservableList(List wrapped) {
        this.wrapped = wrapped;
    }

    public void addListener(Listener l) {
        listeners.add(l);
    }

    public void removeListener(Listener l) {
        listeners.remove(l);
    }

    @Override
    public int size() {
        return wrapped.size();
    }

    @Override
    public boolean isEmpty() {
        return wrapped.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return wrapped.contains(o);
    }

    @Override
    public Iterator<T> iterator() {
        final Iterator<T> iterator = wrapped.iterator();
        return new Iterator<T>() {
            T current = null;

            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public T next() {
                return current = iterator.next();
            }

            @Override
            public void remove() {
                iterator.remove();
                fireRemoved(current);
            }
        };
    }

    private void fireRemoved(T... items) {
        fireRemoved(Arrays.asList(items));
    }

    @Override
    public Object[] toArray() {
        return wrapped.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return wrapped.toArray(a);
    }

    @Override
    public boolean add(T e) {
        if (wrapped.add(e)) {
            fireAdded(e);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean remove(Object o) {
        if (wrapped.remove(o)) {
            fireRemoved((T) o);
            return true;
        }

        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return wrapped.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        if (wrapped.addAll(c)) {
            fireAdded(c);
            return true;
        }

        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        if (wrapped.addAll(index, c)) {
            fireAdded(c);
        }

        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        if (wrapped.removeAll(c)) {
            fireRemoved((Collection<? extends T>) c);
            return true;
        }

        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        if (wrapped.retainAll(c)) {
            fireStracturalChange();
        }

        return false;
    }

    @Override
    public void clear() {
        wrapped.clear();
        fireStracturalChange();
    }

    @Override
    public boolean equals(Object o) {
        return wrapped.equals(o);
    }

    @Override
    public int hashCode() {
        return wrapped.hashCode();
    }

    @Override
    public T get(int index) {
        return wrapped.get(index);
    }

    @Override
    public T set(int index, T element) {
        T old = wrapped.set(index, element);
        fireRemoved(old);
        fireAdded(element);
        return old;
    }

    @Override
    public void add(int index, T element) {
        wrapped.add(index, element);
        fireAdded(element);
    }

    @Override
    public T remove(int index) {
        T old = wrapped.remove(index);
        fireRemoved(old);
        return old;
    }

    @Override
    public int indexOf(Object o) {
        return wrapped.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return wrapped.lastIndexOf(o);
    }

    @Override
    public ListIterator<T> listIterator() {
        return wrapped.listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
        return wrapped.listIterator(index);
    }

    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        return wrapped.subList(fromIndex, toIndex);
    }

    private void fireRemoved(Collection<? extends T> asList) {
        for (Listener<T> l : listeners) {
            l.onItemsRemoved(this, asList);
        }
    }

    private void fireAdded(T... e) {
        fireAdded(Arrays.asList(e));
    }

    private void fireAdded(Collection<? extends T> asList) {
        for (Listener<T> l : listeners) {
            l.onItemsAdded(this, asList);
        }
    }

    private void fireStracturalChange() {
        for (Listener<T> l : listeners) {
            l.onStracturalChange(this);
        }
    }

    public static interface Listener<T> {

        void onItemsAdded(ObservableList<T> source, Collection<? extends T> items);

        void onItemsRemoved(ObservableList<T> source, Collection<? extends T> items);

        void onStracturalChange(ObservableList<T> source);
    }
}

Upvotes: 2

Robert Harvey
Robert Harvey

Reputation: 180868

org.apache.commons.events.observable Class ObservableCollection

Upvotes: 5

yeraycaballero
yeraycaballero

Reputation: 1603

There isn't at least in Java Collections api

http://download-llnw.oracle.com/javase/1.5.0/docs/guide/collections/designfaq.html#27

You can create an wrapper or proxy

Upvotes: 0

Peter Štibran&#253;
Peter Štibran&#253;

Reputation: 32901

If you want to Observe your lists, i.e. be notified when list changes, you can use Glazed Lists.

If you just want to modify objects stored in your lists, you can get your objects by using List.get(int index), or by iterating the list.

If you want to automatically create Beer objects when storing Strings into the list, you'll probably need to write your own simple list wrapper.

Upvotes: 2

broschb
broschb

Reputation: 5006

Sure, you can do this. If you had a class called Soda, you could do:

List<Soda> sodas = new ArrayList<Soda>();
sodas.add(new Soda("Coke"));
sodas.add(new Soda("Sprite"));

Then you could do

sodas.get(1).setSugar(255);

Upvotes: -1

Related Questions