【问题标题】:Java: What is the best way to find elements in a sorted List?Java:在排序列表中查找元素的最佳方法是什么?
【发布时间】:2010-10-14 02:07:44
【问题描述】:

我有一个

List<Cat>

按猫的生日排序。有没有一种有效的 Java 集合方法来查找 1983 年 1 月 24 日出生的所有猫?或者,一般来说什么是好的方法?

【问题讨论】:

  • 我本来打算提交一个答案,但由于 binarySearch 不能保证返回第一个结果,所以那个答案就没有了。

标签: java list collections findall sorted


【解决方案1】:

Collections.binarySearch().

假设猫按生日排序,这将给出其中一只生日正确的猫的索引。从那里,您可以前后迭代,直到找到一个不同生日的人。

如果列表很长和/或同一天生日的猫不多,这应该是直接迭代的重大胜利。

这是我正在考虑的那种代码。请注意,我假设一个random-access 列表;对于链表,你几乎被迭代困住了。 (感谢 fred-o 在 cmets 中指出这一点。)

List<Cat> cats = ...; // sorted by birthday
List<Cat> catsWithSameBirthday = new ArrayList<Cat>();
Cat key = new Cat();
key.setBirthday(...);
final int index = Collections.binarySearch(cats, key);
if (index < 0)
    return catsWithSameBirthday;
catsWithSameBirthday.add(cats.get(index));
// go backwards
for (int i = index-1; i > 0; i--) {
    if (cats.get(tmpIndex).getBirthday().equals(key.getBirthday()))
        catsWithSameBirthday.add(cats.get(tmpIndex));
    else
        break;
}
// go forwards
for (int i = index+1; i < cats.size(); i++) {
    if (cats.get(tmpIndex).getBirthday().equals(key.getBirthday()))
        catsWithSameBirthday.add(cats.get(tmpIndex));
    else
        break;
}
return catsWithSameBirthday;

【讨论】:

  • Collections.binarySearch() 返回单个元素,并且不保证被认为是相同的元素。
  • 也许这会教我在回答之前阅读问题。 :)
  • 另外,Collections.binarySearch() 只对随机访问列表有效。
  • 必须有索引
  • @Jake:好点子,那效果不会很好。我修复了代码。
【解决方案2】:

二分搜索是经典的方法。

澄清:我说你使用二进制搜索。没有一个具体的方法。算法是:

//pseudocode:

index = binarySearchToFindTheIndex(date);
if (index < 0) 
  // not found

start = index;
for (; start >= 0 && cats[start].date == date; --start);
end = index;
for (; end < cats.length && cats[end].date == date; ++end);

return cats[ start .. end ];

【讨论】:

  • Collections.binarySearch() 返回单个元素,并且不保证被认为是相同的元素。
  • 我没说你应该使用Collections.binarySearch 方法。二分查找查找单个元素的索引。所有其他具有相同生日的元素都在找到的元素旁边。您可以通过一个循环获得所有这些。很经典。
  • @Mehrdad - 更新答案以反映这一点,您将获得支持。
【解决方案3】:

Google Collections 可以通过使用谓词并创建谓词匹配日期的过滤集合来做你想做的事。

【讨论】:

  • 它是否过滤 O(n) 中的集合?
  • 我认为它必须这样做,因为它将谓词应用于每个元素。如果列表已排序,则二进制搜索(如赞成的答案)是最好的。
【解决方案4】:

如果您需要快速搜索,请使用以生日为关键字的 HashMap。如果您需要对键进行排序,请使用 TreeMap。

因为你想让多只猫有相同的生日,你需要在 Hast/TreeMap 中使用一个 Collection 作为一个值,例如

      Map<Date,Collection<Cat>>

【讨论】:

    【解决方案5】:

    除非您以某种方式按日期索引集合,否则唯一的方法是遍历所有集合

    【讨论】:

    • 按日期排序。你还能把什么叫做索引!?
    • 我怀疑这是唯一的方式。当然,您可以想象一个“低级”算法,它通过查找具有给定生日的 Cats 的第一次出现并从那里线性处理来非常有效地做到这一点。
    • 杰克:你找到第一个元素的任何算法都是 O(n) ,除非你正在做一些二进制搜索。渐近最快的算法是二分查找,然后线性查找开始和结束。
    猜你喜欢
    • 1970-01-01
    • 2017-06-05
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    相关资源
    最近更新 更多