当前位置: 首页 > 面试题库 >

有限SortedSet

赏彭薄
2023-03-14
问题内容

我正在寻找一个数量有限的SortedSet实现。因此,如果添加了更多元素,则比较器将决定是否添加该元素,并从集合中删除最后一个元素。

SortedSet<Integer> t1 = new LimitedSet<Integer>(3);
t1.add(5);
t1.add(3);
t1.add(1);
// [1,3,5]
t1.add(2);
// [1,2,3]
t1.add(9);
// [1,2,3]
t1.add(0);
// [0,1,2]

标准API中是否有一种优雅的方法可以完成此任务?

我写了一个JUnit测试来检查实现:

@Test
public void testLimitedSortedSet() {
final LimitedSortedSet<Integer> t1 = new LimitedSortedSet<Integer>(3);
t1.add(5);
t1.add(3);
t1.add(1);
System.out.println(t1);
// [1,3,5]
t1.add(2);
System.out.println(t1);
// [1,2,3]
t1.add(9);
System.out.println(t1);
// [1,2,3]
t1.add(0);
System.out.println(t1);
// [0,1,2]
Assert.assertTrue(3 == t1.size());
Assert.assertEquals(Integer.valueOf(0), t1.first());
}

问题答案:

使用标准API,您必须自己完成操作,即扩展已排序的集合类之一,并将所需的逻辑添加到add()addAll()方法。不应该太难。

顺便说一句,我不完全理解你的例子:

t1.add(9);
// [1,2,3]

[1,2,9]之后不应该包含该集合吗?

编辑 :我想现在我明白了:您只想保留添加到集合中的最小3个元素,对吧?

编辑2 :示例实现(未优化)如下所示:

class LimitedSortedSet<E> extends TreeSet<E> {

  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正确指出的,应该删除的第一个元素是index处的元素maxSize。因此,不需要读取(重新添加?)最后一个想要的元素。

重要说明:
正如@DieterDP正确指出的那样,以上实现违反了Collection#add()api合同,该合同规定,如果集合出于某种原因(而不是重复)拒绝添加元素,则
必须 抛出一个例外。

在上面的示例中,首先添加了元素,但是由于大小限制可能会再次将其删除,或者可能会删除其他元素,因此这违反了合同。

为了解决这个问题,您可能想在这些情况下进行更改add()addAll()引发异常(或者在任何情况下都使其无法使用),并提供alterante方法来添加不违反任何现有api合同的元素。

在任何情况下, 都应谨慎 使用上面的示例 因为将其与不知道违规行为的代码 一起 使用可能会导致不必要的调试错误。



 类似资料:
  • 问题内容: 我有表-s在许多一对多的关系与-s 目标是通过单个查询列出球员及其“前三项技能”。 小提琴 查询: 正如您在小提琴中看到的那样,查询结果仅缺少3个技能的限制。 我尝试了子查询的几种变体..联接等等,但是没有任何效果。 问题答案: 一种比较古怪的方法是对结果进行后处理: 当然,这是假设您的技能名称不包含逗号,并且数量很少。 小提琴 一个功能请求用于支持一个明确的条款是可惜还是没有得到解决

  • 问题内容: 我想知道是否有一种方法可以通过我的应用程序进行一次往返操作来在Redis中执行此操作: 对于给定的键,其可能的值是范围内的任何整数。基本上,它具有上下边界。 当发出or 命令时(例如), 仅 当结果值没有超出范围 时才 执行。 我需要这个操作是原子的,并且我想知道是否有一种方法可以避免为此编写Lua脚本。 谢谢。 问题答案: 这个答案可能不是您所期望的。但是我不得不说,Lua脚本是非常

  • 概述 Javascript Finite State Machine函数库 参考链接 概述 有限状态机(Finite-state machine)是一个非常有用的模型,可以模拟世界上大部分事物。 简单说,它有三个特征: 状态总数(state)是有限的。 任一时刻,只处在一种状态之中。 某种条件下,会从一种状态转变(transition)到另一种状态。 它对JavaScript的意义在于,很多对象可

  • 我试图在一个没有权限在WildFly主目录和子目录中写入的用户下启动WildFly 8.2。为此,我已经将目录复制到用户主目录。下面是我用来在cygwin中启动WildFly的命令: 这是这个命令的输出: 正如您在上面的日志中看到的,首先WildFly尝试写入,即使命令行中指出了另一个目录作为服务器基本目录。由于缺乏权限而无法在那里写入WildFly继续正常启动服务器。 有没有办法让WildFly

  • 是否有一种方法/pattern来实现? promise-数组包含构造和返回promise的函数 应在所有解析后解析 只有promise应并行运行 第n+1个promise应在n个完成后立即开始。以便始终有解析器并行运行。

  • 问题内容: 具体说说(服务器端)V8,并假设我不担心准确性,因为我可以检测和补偿它,那么我可以使用setTimeout 逐字 间隔设置几千个相对简单的超时,而无需面对任何其他限制除了RAM以外?如果我要使用一个在任何给定时间可能有数千个计划的超时的系统,我应该注意什么吗? 作为记录,我已经阅读了John’s Resig关于Javascript计时器如何工作的出色文章,因此无需指出那里已经介绍的内容