为什么 JavaFX 中没有 ObservableQueues?
Why are there no ObservableQueues in JavaFX?
为什么 JavaFX 中没有 ObservableQueue?如果我们查看 FXCollections 的 Java 9 文档(只是为了查看与 8 相比是否有任何更改),我们会看到用于创建 Observable 集、列表和映射的静态辅助方法。还有一些方法可以创建 Observable 浮点数和整数数组。但是,无法创建 ObservableQueue。 Java中的Queue接口有很多有趣的实现,包括ArrayDeque、DelayQueue、ConcurrentLinkedQueue、PriorityQueue等。JavaFX中不支持创建ObservableQueue的逻辑是什么。
正如@TomasMikula 在@eckig(现已删除)的回答中评论的那样,可能只是对 ObservableQueue
的需求不足。如果你有一个可靠的用例,你应该考虑 submitting a feature request。
与此同时,通过子类化 ObservableListBase
并包装一个 Queue
执行。子类化 ObservableListBase
是 "quick" 部分,也是 "dirty" 部分,因为您暴露了 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());
}
}
为什么 JavaFX 中没有 ObservableQueue?如果我们查看 FXCollections 的 Java 9 文档(只是为了查看与 8 相比是否有任何更改),我们会看到用于创建 Observable 集、列表和映射的静态辅助方法。还有一些方法可以创建 Observable 浮点数和整数数组。但是,无法创建 ObservableQueue。 Java中的Queue接口有很多有趣的实现,包括ArrayDeque、DelayQueue、ConcurrentLinkedQueue、PriorityQueue等。JavaFX中不支持创建ObservableQueue的逻辑是什么。
正如@TomasMikula 在@eckig(现已删除)的回答中评论的那样,可能只是对 ObservableQueue
的需求不足。如果你有一个可靠的用例,你应该考虑 submitting a feature request。
与此同时,通过子类化 ObservableListBase
并包装一个 Queue
执行。子类化 ObservableListBase
是 "quick" 部分,也是 "dirty" 部分,因为您暴露了 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());
}
}