【问题标题】:Extract first k elements from a Set efficiently有效地从 Set 中提取前 k 个元素
【发布时间】:2014-10-26 22:08:17
【问题描述】:

问题

我正在编写一个简单的 Java 程序,其中有一个 TreeSet,其中包含 Comparable 元素(这是我自己编写的一个类)。在特定时刻,我需要从中获取前 k 个元素。

我做了什么

目前我为我的问题找到了两种不同的解决方案:

  1. 使用我写的一个简单的方法;它从初始 TreeSet 复制前 k 个元素;
  2. 使用 Google Guava greatestOf 方法。

对于第二个选项,您需要以这种方式调用该方法: Ordering.natural().greatestOf(mySet, 80))

但我认为使用这种调用是没有用的,因为元素已经排序。我错了吗?

问题

我想在这里问一下,获取包含TreeSet 的前k 个元素的Collection 派生类的正确且有效的方法是什么?

其他信息

Java 版本:>= 7

【问题讨论】:

  • 如果原来的Set 发生变化,您是否希望新集合也发生变化?如果是这样,您可以将 Set 包装在另一个对象中 - 一种非常有效的机制。
  • 生成的Set 永远不会被修改。
  • 我还不想关闭,但它似乎部分欺骗了this thread,至少在它的算法部分。
  • "...元素已排序..." java.util.SortedSet 的元素已排序。 java.util.Set 的元素没有定义的顺序。 (也就是说,允许 Set 的实现以任何顺序迭代其元素。)
  • @jameslarge 我已经编辑了我的问题。

标签: java algorithm


【解决方案1】:

我建议您使用TreeSet<YourComparableClass> 集合,这似乎是您正在寻找的解决方案。

一个 TreeSet 可以返回一个迭代器,你可以简单地迭代 K 次,通过存储迭代器返回给你的对象:元素将按顺序返回给你。

此外,TreeSet 使您的元素始终保持排序:在任何时候,当您添加或删除元素时,它们会被插入和删除,以便结构保持有序。

这是一个可能的例子:

public static ArrayList<YourComparableClass> getFirstK(TreeSet<YourComparableClass> set, int k) {
    Iterator<YourComparableClass> iterator = set.iterator();
    ArrayList<YourComparableClass> result = new ArrayList<>(k); //to store first K items
    for (int i=0;i<k;i++) result.add(iterator.next()); //iterator returns items in order
    //you should also check iterator.hasNext(); if you are not sure to have always a K<set.size()
    return result;
}

【讨论】:

  • 这个答案可能与我的第一个解决方案有关。对吗?
  • @AlessandroSuglia 是的,现在你已经编辑了你的问题更清楚你已经想到了这种解决方案
  • 感谢您的建议。但是我认为如果有真正好的东西可用,再写一个方法是没有用的:)
  • @AlessandroSuglia 实际上 TreeSet 是唯一满足您要求的集合,但它没有提供像您描述的那样的方法,所以如果您想使用 TreeSet 这是更简单的方法.. 如果你想使用番石榴,那就另当别论了 ;)
  • 你可以在一个语句中更优雅地做到这一点:return (ArrayList&lt;YourComparableClass&gt;) set.stream().limit(k).collect(Collectors.toList());
【解决方案2】:

descendingIterator() method of java.util.TreeSet 产生从最大到最小的元素,因此您可以多次执行它,将元素插入到集合中。运行时间为 O(log n + k),其中 k 是返回的元素数,这肯定足够快。

另一方面,如果您使用的是HashSet,则元素实际上是排序的,因此您需要使用您指定的线性时间选择方法。

【讨论】:

    【解决方案3】:

    你可以使用 Guava 的Iterables#limit:

    ImmutableList.copyOf(Iterables.limit(yourSet, 7))
    

    http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Iterables.html#limit(java.lang.Iterable, int)

    【讨论】:

    • 我正在尝试您的解决方案,它似乎是最好的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 2020-10-28
    • 1970-01-01
    • 2011-01-15
    • 2011-11-09
    相关资源
    最近更新 更多