Java 番石榴中的不可变优先级队列

Java 番石榴中的不可变优先级队列,java,performance,guava,immutability,Java,Performance,Guava,Immutability,我尝试使用Guava库创建不可变优先级队列。作为队列“后端”,我使用ImmutableSortedMultiset。但我有一个性能问题-操作推送和弹出非常缓慢。从已排序的不可变集合中添加和删除单个项的最佳方法是什么? 谢谢 这是我的代码: 公共类ImmutablePriorityQueue实现PriorityQueue{ 私有最终ImmutableSortedMultiset多集; 私有ImmutablePriorityQueue(){ 这是(ImmutableSortedMultiset.of

我尝试使用Guava库创建不可变优先级队列。作为队列“后端”,我使用ImmutableSortedMultiset。但我有一个性能问题-操作推送和弹出非常缓慢。从已排序的不可变集合中添加和删除单个项的最佳方法是什么? 谢谢

这是我的代码:

公共类ImmutablePriorityQueue实现PriorityQueue{
私有最终ImmutableSortedMultiset多集;
私有ImmutablePriorityQueue(){
这是(ImmutableSortedMultiset.of());
}
专用ImmutablePriorityQueue(ImmutableSortedMultiset多集){
this.multiset=multiset;
}
公共静态优先级队列createEmpty(){
返回新的ImmutablePriorityQueue();
}
@凌驾
公共T peek(){
如果(isEmpty())抛出新的EmptyCollectionException();
返回multiset.firstEntry().getElement();
}
@凌驾
公共优先级队列推送(T元素){
ImmutableSortedMultiset.Builder=multiset.naturalOrder();
返回新的ImmutablePriorityQueue(builder.add(element).addAll(multiset.asList()).build());
}
@凌驾
公共优先级队列pop(){
如果(isEmpty())抛出新的EmptyCollectionException();
ImmutableSortedMultiset.Builder=multiset.naturalOrder();
返回新的ImmutablePriorityQueue(builder.addAll(multiset.asList().subList(1,size())).build());
}
@凌驾
公共优先级队列清除(){
返回新的ImmutablePriorityQueue();
}
@凌驾
公共整数大小(){
返回multiset.size();
}
@凌驾
公共布尔值为空(){
返回multiset.isEmpty();
}
}
这看起来更像一个“CopyOnWrite”数据结构,至少在Java中是这样调用的。您可能想看看
CopyOnWriteArrayList
的实现,但它的不同之处在于它不返回对象的副本,而是锁定内部状态并创建对象的副本

番石榴中的不可变对象通常禁止对对象进行修改,即从
不可变列表中摘录:

@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);
您可能还需要返回一对新创建的集合和一个被弹出的元素,以避免丢失一个被弹出的元素。这只是一个想法,我不确定这种方法是否在任何地方使用。

这看起来更像一个“CopyOnWrite”数据结构,至少在Java中是这样调用的。您可能想看看
CopyOnWriteArrayList
的实现,但它的不同之处在于它不返回对象的副本,而是锁定内部状态并创建对象的副本

番石榴中的不可变对象通常禁止对对象进行修改,即从
不可变列表中摘录:

@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);

您可能还需要返回一对新创建的集合和一个被弹出的元素,以避免丢失一个被弹出的元素。这只是一个想法,我不确定这种方法是否在任何地方使用。

pop()方法的意义是什么?它甚至不返回已弹出的元素?为什么在不可变队列中会有push()和pop()方法?Adn为什么使用多集实现队列?我认为你走错了路。你想用这个队列实现什么?@JBNizet我想OP使用的是一个排序的多集,因为它需要排序,并且同一个元素可以多次出现在集合中。我同意你的其他观点。不变的意思是:它不会改变。推送和弹出是变化。这里有一个矛盾。您想对不可变队列做什么?正如我所说的,pop()应该返回已弹出的内容,否则该方法将毫无用处。您还没有解释为什么需要不可变队列。队列通常是可变的,因为它用于不断地推送和弹出。没有一种Guava类型能够有效地表示这种类型的数据结构。你必须自己动手。pop()方法的意义是什么?它甚至不返回已弹出的元素?为什么在不可变队列中会有push()和pop()方法?Adn为什么使用多集实现队列?我认为你走错了路。你想用这个队列实现什么?@JBNizet我想OP使用的是一个排序的多集,因为它需要排序,并且同一个元素可以多次出现在集合中。我同意你的其他观点。不变的意思是:它不会改变。推送和弹出是变化。这里有一个矛盾。您想对不可变队列做什么?正如我所说的,pop()应该返回已弹出的内容,否则该方法将毫无用处。您还没有解释为什么需要不可变队列。队列通常是可变的,因为它用于不断地推送和弹出。没有一种Guava类型能够有效地表示这种类型的数据结构。你必须自己动手。谢谢你的回复。我不能使用Tail,因为如果集合中有重复的值,则不可能使用Tail。CopySorded没问题,但我如何才能更快地添加或删除单个项目?我已经更新了答案,以说明
tail()
应用程序。我不确定我是否理解您要如何删除单个项目。不可能从不变的番石榴收藏中删除一个项目。您可以使用
remove()
或从常规集合中删除项,即
TreeMultiset