【问题标题】:Equivalent of C# ObservableCollection in Java等效于 Java 中的 C# ObservableCollection
【发布时间】:2009-10-11 20:29:10
【问题描述】:

我想知道是否有一个像 OberservableCollection 一样的数据结构,就像在 C# 中一样,能够采用某种类型。

例如:

在 C# 中我可以说..

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

假设制作了Beer类,我们可以改变酒精含量,这样

 Beer[1].content = 5;

我想知道是否有人知道是否有这样的数据结构可以与 Java 一起使用。


我是一名 C# 程序员,不是一个 Java 程序员,所以我只是想知道。此外,它必须能够接受自定义类型,而不是泛型。

【问题讨论】:

  • 可观察集合的主要特点是您可以观察它的变化 - 即在添加/删除列表中的任何内容时获取事件。这是你需要的吗?

标签: java data-structures


【解决方案1】:

org.apache.commons.events.observable Class ObservableCollection

【讨论】:

  • 请注意,这个事件库不稳定​​,也没有积极开发,因为它位于 apache commons 的休眠分支中。因此,您将找不到该库的任何发布版本。
【解决方案2】:

可观察数据结构(ObservableListObservableMap 等)作为JavaFX 项目的一部分包含在 Oracle Java 7u6+ 中。对应的 OpenJDK 库由 OpenJFX 项目提供。

这是using JavaFX collections的教程。

还有一些使用链接教程中的 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());
  }
}

【讨论】:

    【解决方案3】:

    如果您想观察您的列表,即在列表更改时收到通知,您可以使用Glazed Lists

    如果您只想修改存储在列表中的对象,您可以使用List.get(int index) 或通过迭代列表来获取您的对象。

    如果您想在将字符串存储到列表中时自动创建 Beer 对象,您可能需要编写自己的简单列表包装器。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        至少在 Java Collections api 中没有

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

        你可以创建一个包装器或代理

        【讨论】:

          【解决方案6】:

          你可以考虑使用 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 时,都会通知两个观察者。

          【讨论】:

            【解决方案7】:

            当然,您可以这样做。如果你有一个名为 Soda 的课程,你可以这样做:

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

            那你就可以了

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

            【讨论】:

            • 为什么要使用 ArrayList 而不是 List
            • List 是接口,arraylist 是实现。通用标签没有显示我刚刚添加的代码标签。(快乐 Snarfblam)
            猜你喜欢
            • 1970-01-01
            • 2012-03-24
            • 1970-01-01
            • 1970-01-01
            • 2012-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-03
            相关资源
            最近更新 更多