2015-02-11 5 views
6

Warum gibt es in JavaFX keine ObservableQueue? Wenn wir für FXCollections die Java 9-Dokumentation betrachten (nur um zu sehen, ob es Änderungen von 8 gibt), sehen wir statische Hilfsmethoden, um Observable-Sets, Listen und Maps zu erstellen. Es gibt auch einige Methoden zum Erstellen von Observable-Float- und Integer-Arrays. Es gibt jedoch keine Möglichkeit, eine ObservableQueue zu erstellen. Die Warteschlangenschnittstelle in Java hat viele interessante Implementierungen, einschließlich ArrayDeque, DelayQueue, ConcurrentLinkedQueue, PriorityQueue usw. Was ist die Logik hinter dem Grund, warum es keine Unterstützung für die Erstellung von ObservableQueues in JavaFX gibt?Warum gibt es in JavaFX keine ObservableQueues?

Antwort

6

Da @TomasMikula Kommentare in @ eckigs (jetzt gelöschte) Antwort gibt, gibt es wahrscheinlich nicht genug Nachfrage für eine ObservableQueue. Wenn Sie einen soliden Anwendungsfall haben, sollten Sie submitting a feature request in Betracht ziehen.

In der Zwischenzeit ist es nicht allzu schwer, eine schnelle und unsaubere ObservableQueue Umsetzung Queue und das Hinzufügen von „Beobachtbarkeit“ durch eine Queue Implementierung Subklassen ObservableListBase und Verpackung zu schaffen. Subclassing ObservableListBase ist der "schnelle" Teil, aber auch der "schmutzige" Teil, weil Sie List Methoden sowie Queue Methoden aussetzen; da eine beliebige Queue hat keine get(int index) die einzige Möglichkeit zu implementieren, dass (die ich sehen kann) ist bis zu index durchlaufen. Alles, was get verwendet, um durch die ObservableQueue zu durchlaufen, in Bezug auf es als List, wird in O(n^2) Zeit ausgeführt. Mit diesem Vorbehalt sollte Folgendes ziemlich gut funktionieren:

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

} 

Sie ListChangeListener s mit diesem Register können von Änderungen an der Warteschlange benachrichtigt. (Beachten Sie, dass Sie, wenn Sie Extraktoren unterstützen und Benachrichtigungen aktualisieren möchten, etwas mehr Arbeit benötigen ...).

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

}