为什么 JavaFX 中没有 ObservableQueues? [英] Why are there no ObservableQueues in JavaFX?

查看:27
本文介绍了为什么 JavaFX 中没有 ObservableQueues?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 JavaFX 中没有 ObservableQueue?如果我们查看 FXCollections 的 Java 9 文档(只是想看看 8 是否有任何更改),我们会看到用于创建 Observable 集、列表和映射的静态辅助方法.还有一些方法可以创建 Observable 浮点和整数数组.但是,没有办法创建 ObservableQueue.Java中的Queue接口有很多有趣的实现,包括ArrayDeque、DelayQueue、ConcurrentLinkedQueue、PriorityQueue等.JavaFX中不支持创建ObservableQueues背后的逻辑是什么.

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 methods to create Observable sets, lists, and maps. There are also some methods to create Observable float and integer arrays. However, there is no way to create an ObservableQueue. The Queue interface in Java has many interesting implementations, including ArrayDeque, DelayQueue, ConcurrentLinkedQueue, PriorityQueue, etc. What is the logic behind the reason why there is no support for creating ObservableQueues in JavaFX.

推荐答案

正如@TomasMikula 在@eckig(现已删除)答案中的评论,可能只是对 ObservableQueue 的需求不够.如果您有可靠的用例,您应该考虑提交功能请求.

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.

与此同时,创建一个快速而简单的 ObservableQueue 实现 Queue 并通过子类化 ObservableListBase 并包装一个 Queue 实现.子类化 ObservableListBase 是快速"部分,但也是脏"部分,因为您公开了 List 方法以及 Queue 方法;因为任意 Queue 没有 get(int index) 实现它的唯一方法(我可以看到)是迭代到 index.任何使用 get 遍历 ObservableQueue 的东西,将其视为 List,都将在 O(n^2)时间.有了这个警告,以下应该可以很好地工作:

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

}

您可以使用此注册 ListChangeListener,以便在队列修改时收到通知.(注意,如果你想支持提取器和更新通知,你需要做更多的工作......).

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

}

这篇关于为什么 JavaFX 中没有 ObservableQueues?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆