Эквивалент C # ObservableCollection в Java - PullRequest
12 голосов
/ 12 октября 2009

Мне было интересно, есть ли структура данных, которая действует как OberservableCollection, почти как в C #, которая может принимать определенный тип.

например:

В C # я могу сказать ..

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

Предполагается, что класс пива сделан и мы можем изменить содержание алкоголя так, чтобы

 Beer[1].content = 5;

Мне было интересно, знает ли кто-нибудь, существует ли такая структура данных, которая также работает с Java.


Я программист на C #, не так много программистов на Java, поэтому просто удивляюсь. Кроме того, он должен иметь возможность принимать пользовательский тип, а не универсальный.

Ответы [ 7 ]

5 голосов
/ 12 октября 2009

org.apache.commons.events.observable Класс ObservableCollection

3 голосов
/ 09 мая 2013

Наблюдаемые структуры данных ( ObservableList , ObservableMap и т. Д.) Включены в Oracle Java 7u6 + как часть проекта JavaFX . Соответствующая библиотека для OpenJDK предоставляется проектом OpenJFX .

Вот учебник по с использованием коллекций JavaFX .

И некоторый пример кода для использования наблюдаемого списка JavaFX из связанного руководства:

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());
  }
}
2 голосов
/ 09 мая 2013

JavaFX теперь имеет ObservableList, который соответствует вашим потребностям, в случае, если вы не хотите зависеть от JavaFX - вот класс, который я написал некоторое время назад, который можно использовать вместо него.

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);
    }
}
2 голосов
/ 12 октября 2009

Если вы хотите наблюдать за своими списками, то есть получать уведомления об изменениях списков, вы можете использовать Застекленные списки .

Если вы просто хотите изменить объекты, хранящиеся в ваших списках, вы можете получить ваши объекты, используя List.get (int index) или итерируя список.

Если вы хотите автоматически создавать объекты Beer при сохранении строк в списке, вам, вероятно, потребуется написать собственную простую оболочку списка.

0 голосов
/ 22 июля 2016

Вы можете рассмотреть возможность использования класса java.util.Observable, вот пример:

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");

  }
}

Таким образом, каждый раз, когда ArrayList получает доступ, два наблюдателя получают уведомление.

0 голосов
/ 08 августа 2010

Нет, по крайней мере, в Java Collections api

http://download -llnw.oracle.com / JavaSE / 1.5.0 / Docs / руководство / коллекции / designfaq.html # 27

Вы можете создать оболочку или прокси

0 голосов
/ 12 октября 2009

Конечно, вы можете сделать это. Если бы у вас был класс Soda, вы могли бы сделать:

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

Тогда вы могли бы сделать

sodas.get(1).setSugar(255);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...