2015-02-11 47 views
6

为什么JavaFX中没有ObservableQueue?如果我们查看FXCollections的Java 9文档(仅查看是否有任何更改,请参阅8),我们将看到静态助手方法来创建Observable集合,列表和映射。还有一些方法可以创建Observable float和integer数组。但是,无法创建ObservableQueue。 Java中的Queue接口有许多有趣的实现,包括ArrayDeque,DelayQueue,ConcurrentLinkedQueue,PriorityQueue等。在JavaFX中不支持创建ObservableQueues的原因背后有什么逻辑。为什么JavaFX中没有ObservableQueues?

回答

6

由于@TomasMikula在@ eckig(现已删除)的回答中留言,可能对ObservableQueue的需求不足。如果你有一个坚实的用例,你应该考虑submitting a feature request

在此期间,这不是太努力创造一个快速和肮脏的ObservableQueue实施Queue和通过继承ObservableListBase和包装一个Queue实现加入“可观性”。子类ObservableListBase是“快速”部分,也是“脏”部分,因为您公开了List方法以及Queue方法;因为任意Queue没有get(int index)实现这个(我可以看到)的唯一方法是迭代达到index。任何使用get来遍历ObservableQueue,关于它作为List,将运行在O(n^2)时间。做了这番解释,下面应该工作得很好:

import java.util.LinkedList; 
import java.util.Queue; 

import javafx.collections.ObservableListBase; 


public class ObservableQueue<E> extends ObservableListBase<E> implements Queue<E> { 

    private final Queue<E> queue ; 


    /** 
    * Creates an ObservableQueue backed by the supplied Queue. 
    * Note that manipulations of the underlying queue will not result 
    * in notification to listeners. 
    * 
    * @param queue 
    */ 
    public ObservableQueue(Queue<E> queue) { 
     this.queue = queue ; 
    } 

    /** 
    * Creates an ObservableQueue backed by a LinkedList. 
    */ 
    public ObservableQueue() { 
     this(new LinkedList<>()); 
    } 

    @Override 
    public boolean offer(E e) { 
     beginChange(); 
     boolean result = queue.offer(e); 
     if (result) { 
      nextAdd(queue.size()-1, queue.size()); 
     } 
     endChange(); 
     return result ; 
    } 

    @Override 
    public boolean add(E e) { 
     beginChange() ; 
     try { 
      queue.add(e); 
      nextAdd(queue.size()-1, queue.size()); 
      return true ; 
     } finally { 
      endChange(); 
     } 
    } 


    @Override 
    public E remove() { 
     beginChange(); 
     try { 
      E e = queue.remove(); 
      nextRemove(0, e); 
      return e; 
     } finally { 
      endChange(); 
     } 
    } 

    @Override 
    public E poll() { 
     beginChange(); 
     E e = queue.poll(); 
     if (e != null) { 
      nextRemove(0, e); 
     } 
     endChange(); 
     return e ; 
    } 

    @Override 
    public E element() { 
     return queue.element(); 
    } 

    @Override 
    public E peek() { 
     return queue.peek(); 
    } 

    @Override 
    public E get(int index) { 
     Iterator<E> iterator = queue.iterator(); 
     for (int i = 0; i < index; i++) iterator.next(); 
     return iterator.next(); 
    } 

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

} 

你可以用这个注册ListChangeListener s到通知修改队列。 (请注意,如果你想支持提取器和更新通知,你需要做更多的工作......)。

import javafx.collections.ListChangeListener.Change; 

public class ObservableQueueTest { 
    public static void main(String[] args) { 
     ObservableQueue<String> oq = new ObservableQueue<>(); 
     oq.addListener((Change<? extends String> change) -> { 
      while (change.next()) { 
       if (change.wasAdded()) { 
        System.out.println("Added: "+change.getAddedSubList()); 
       } 
       if (change.wasRemoved()) { 
        System.out.println("Removed: "+change.getRemoved()); 
       } 
       if (change.wasUpdated()) { 
        System.out.println("Updated: "+oq.subList(change.getFrom(), change.getTo())); 
       } 
       if (change.wasReplaced()) { 
        System.out.println("Replaced"); 
       } 
      } 
     }); 

     oq.offer("One"); 
     oq.offer("Two"); 
     oq.offer("Three"); 

     System.out.println("Peek: "+oq.peek()); 
     System.out.println("Remove..."); 
     System.out.println(oq.remove()); 

     System.out.println("Element:"); 
     System.out.println(oq.element()); 

     System.out.println("get(1): "+oq.get(1)); 

     System.out.println("Poll: "); 
     System.out.println(oq.poll()); 

     System.out.println("Poll again:"); 
     System.out.println(oq.poll()); 

     System.out.println("Poll should return null:"); 
     System.out.println(oq.poll()); 

     System.out.println("Element should throw exception:"); 
     System.out.println(oq.element()); 
    } 

}