Why are there no ObservableQueues in JavaFX?

前端 未结 1 1770
感情败类
感情败类 2021-01-12 07:02

Why are there no ObservableQueue in JavaFX? If we look at the Java 9 documentation (just to see if there are any changes from 8) for FXCollections, we see static helper meth

相关标签:
1条回答
  • 2021-01-12 07:15

    As @TomasMikula comments in @eckig's (now-deleted) answer, there probably just is not enough demand for an ObservableQueue. If you have a solid use-case, you should consider submitting a feature request.

    In the meantime, it's not too hard to create a quick-and-dirty ObservableQueue implementing Queue and adding "observability" by subclassing ObservableListBase and wrapping a Queue implementation. Subclassing ObservableListBase is the "quick" part, but also the "dirty" part because you expose List methods as well as Queue methods; since an arbitrary Queue doesn't have a get(int index) the only way to implement that (that I can see) is to iterate through up to index. Anything that uses get to iterate through the ObservableQueue, regarding it as a List, will run in O(n^2) time. With that caveat, the following should work pretty well:

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

    You can register ListChangeListeners with this to be notified of modifications to the queue. (Note that if you want to support extractors and update notifications, you'd need to do quite a bit more work...).

    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());
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题