使用标准API,您必须自己完成,即扩展其中一个已排序的集合类,并将所需的逻辑添加到add()和addAll()方法.不应该太难.
顺便说一句,我不完全理解你的例子:
t1.add(9);
// [1,2,3]
之后套装不应该包含[1,2,9]吗?
编辑:我想现在我明白了:你只想保留添加到集合中的最小3个元素,对吧?
编辑2:示例实现(未优化)可能如下所示:
class LimitedSortedSet extends TreeSet {
private int maxSize;
LimitedSortedSet( int maxSize ) {
this.maxSize = maxSize;
}
@Override
public boolean addAll( Collection extends E> c ) {
boolean added = super.addAll( c );
if( size() > maxSize ) {
E firstToRemove = (E)toArray( )[maxSize];
removeAll( tailSet( firstToRemove ) );
}
return added;
}
@Override
public boolean add( E o ) {
boolean added = super.add( o );
if( size() > maxSize ) {
E firstToRemove = (E)toArray( )[maxSize];
removeAll( tailSet( firstToRemove ) );
}
return added;
}
}
请注意,tailSet()返回包含参数的子集(如果在集合中).这意味着如果您无法计算下一个更高的值(不需要在集合中),您将必须读取该元素.这是在上面的代码中完成的.
如果您可以计算下一个值,例如如果你有一组整数,那么做一些tailSet(lastElement 1)就足够了,你不必读取最后一个元素.
或者,您可以自己迭代该集合,并删除您想要保留的最后一个元素.
另一个替代方案,虽然可能更多工作,但是在插入元素之前检查大小并相应地移除.
更新:正如msandiford正确指出的那样,应该删除的第一个元素是索引maxSize的元素.因此,不需要读取(重新添加?)最后想要的元素.
重要的提示:
正如@DieterDP正确指出的那样,上面的实现违反了Collection#add()api契约,该契约声明如果集合因为复制而拒绝添加元素,则必须抛出一个excpetion.
在上面的示例中,首先添加元素,但由于大小限制可能会再次删除元素,或者可能会删除其他元素,因此这违反了合同.
要解决此问题,您可能需要更改add()和addAll()以在这些情况下抛出异常(或者在任何情况下为了使它们无法使用)并提供alterante方法来添加不违反任何现有api契约的元素.
在任何情况下都应谨慎使用上述示例,因为使用不具备违规行为的代码可能会导致不必要且难以调试的错误.