2013-12-22 3 views
0

Я пытаюсь сделать неизменяемую очередь приоритетов с помощью библиотеки Guava. В качестве «backend» в очереди я использовал ImmutableSortedMultiset. Но у меня проблема с производительностью - толчок работы и поп очень медленные. Каков наилучший способ добавить и удалить отдельный элемент из сортированной неизменяемой коллекции? Спасибо!Неизменяемая очередь приоритетов в Guava

Это мой код:

public class ImmutablePriorityQueue<T extends Comparable<T>> implements PriorityQueue<T> { 

    private final ImmutableSortedMultiset<T> multiset; 

    private ImmutablePriorityQueue() { 
     this(ImmutableSortedMultiset.<T>of()); 
    } 

    private ImmutablePriorityQueue(ImmutableSortedMultiset<T> multiset) { 
     this.multiset = multiset; 
    } 

    public static <T extends Comparable<T>> PriorityQueue<T> createEmpty() { 
     return new ImmutablePriorityQueue<T>(); 
    } 

    @Override 
    public T peek() { 
     if (isEmpty()) throw new EmptyCollectionException(); 
     return multiset.firstEntry().getElement(); 
    } 

    @Override 
    public PriorityQueue<T> push(T element) { 
     ImmutableSortedMultiset.Builder<T> builder = multiset.naturalOrder(); 
     return new ImmutablePriorityQueue<T>(builder.add(element).addAll(multiset.asList()).build()); 
    } 

    @Override 
    public PriorityQueue<T> pop() { 
     if (isEmpty()) throw new EmptyCollectionException(); 
     ImmutableSortedMultiset.Builder<T> builder = multiset.naturalOrder(); 
     return new ImmutablePriorityQueue<T>(builder.addAll(multiset.asList().subList(1, size())).build()); 
    } 

    @Override 
    public PriorityQueue<T> clear() { 
     return new ImmutablePriorityQueue<T>(); 
    } 

    @Override 
    public int size() { 
     return multiset.size(); 
    } 

    @Override 
    public boolean isEmpty() { 
     return multiset.isEmpty(); 
    } 
} 
+6

В чем смысл метода pop()? Он даже не возвращает элемент, который был выбит? И почему бы существовать метод push() и pop() в * неизменяемой * очереди? Adn зачем использовать мультимножество для реализации очереди? Я думаю, вы на неправильном пути. Чего вы хотите достичь в этой очереди? –

+0

@JBNizet Я полагаю, что OP использует отсортированный мультимножество, потому что его нужно сортировать, и один и тот же элемент может быть в множестве несколько раз. Я согласен с другими вашими соображениями. –

+0

Я хочу неизменный объект - очередь приоритетов. Вот почему я реализовал методы push и pop. Эти методы типичны для очереди приоритетов. Как я могу добавить отдельный элемент в отсортированную неизменяемую коллекцию? Каков наилучший способ? Метод pop удаляется первым (с наивысшим приоритетом) элементом из очереди приоритетов. –

ответ

4

Это больше похоже на структуру данных «CopyOnWrite», по крайней мере, это то, как это называется в Java. Возможно, вам стоит взглянуть на реализацию CopyOnWriteArrayList, но все же это отличается тем, что она не возвращает копию объекта, а блокирует внутреннее состояние и создает его копию.

Неизменные объекты гуавы обычно запрещают изменения, внесенные в объект, то есть отрывок из ImmutableList:

@Deprecated 
@Override 
public final E set(int index, E element) { 
    throw new UnsupportedOperationException(); 
} 

Теперь, что касается производительности pop() операции asList() создаст временный массив для хранения элементов, так создавая копию таким образом, предположительно, имеют меньшие накладные расходы:

TreeMultiset<String> original = TreeMultiset.create(Arrays.asList("a", "b", "a", "c", "b", "d")); 
System.out.println("original: " + original); 

SortedMultiset<String> tail = ImmutableSortedMultiset.copyOfSorted(original.tailMultiset(original.firstEntry().getElement(), BoundType.OPEN)); 
System.out.println("tail: " + tail); 

идея заключается в том, чтобы взять первую запись и запрос для диапазона с ним быть оставлена ​​открытой границей (меня aning "исключая"). Эта печать:

original: [a x 2, b x 2, c, d] 
tail: [b x 2, c, d] 

Вы также должны вернуть пару вновь созданной коллекции и элемент, который был хлопнутым для не потерять элемент, который выскочил. Это всего лишь идея, я не уверен, что этот подход используется где угодно.

+0

Спасибо за ваш ответ. Хвост Я не могу использовать, потому что это невозможно, если у меня есть повторяющиеся значения в коллекции. CopySorted в порядке, но как я могу быстрее добавить или удалить отдельный элемент? –

+1

Я обновил ответ, чтобы проиллюстрировать приложение 'tail()'.Я не уверен, что понимаю, как вы хотите удалить один элемент. Невозможно удалить элемент из неизменной коллекции Guava. Вы можете удалить элемент из регулярной коллекции, т. Е. «TreeMultiset» с помощью 'remove()', или вы можете вернуть измененную копию неизменяемого объекта, который вы делаете. –

Смежные вопросы