为什么JavaFX中没有ObservableQueues?

brc*_*low 8 java queue javafx observablelist

为什么JavaFX中没有ObservableQueue?如果我们查看FXCollections的Java 9文档(只是为了查看是否有任何更改),我们会看到静态帮助器方法来创建Observable集,列表和映射.还有一些方法可以创建Observable浮点数和整数数组.但是,无法创建ObservableQueue.Java中的Queue接口有许多有趣的实现,包括ArrayDeque,DelayQueue,ConcurrentLinkedQueue,PriorityQueue等.为什么不支持在JavaFX中创建ObservableQueues的原因是什么.

Jam*_*s_D 7

正如@TomasMikula在@ eckig(现已删除)的回答中所评论的那样,可能只是没有足够的需求ObservableQueue.如果您有一个可靠的用例,则应考虑提交功能请求.

与此同时,创建一个快速而肮脏的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();
    }

}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)