【问题标题】:What is the most efficient way to check if item exists in Arraylist? [duplicate]检查 Arraylist 中是否存在项目的最有效方法是什么? [复制]
【发布时间】:2013-07-04 08:02:35
【问题描述】:

最有效的方法是什么?

我有一个名为 windowList 的 ArrayList 列表。

GameWindow 是具有 startTime 和 endTime 的 bean。

对于我收到的每个对象,我需要检查对象的窗口是否属于任何此 windowList 值。我需要为数百万个值这样做。

请帮助我以最有效的方式做到这一点......

【问题讨论】:

  • 您能否为您收到的对象添加类代码以及问题中的“属于”是什么意思?
  • 最有效的方法是将您的元素放在排序的集合中并执行散列或二进制搜索。
  • 我已经编辑了我的答案;我认为它应该很好地满足您的需求
  • 我不同意上述问题已经回答了这个问题,对不起......
  • 调用重新打开的原因:这是一个XY问题;虽然 OP 要求检查列表中某个元素的存在,但实际上他的问题与此大不相同:这是一个区间问题。

标签: java apache jakarta-ee collections


【解决方案1】:

建议:放弃您的ArrayList 并使用SortedMaps。我们在这里假设两件事:

  • 您的开始和结束时间是 long(注意:为 Java 7 编写的代码);
  • 您的GameWindow 类正确实现了.equals().hashCode()

鉴于这些先决条件,编写一个专用类(例如,GameWindowList 或其他东西),您可以在其中声明:

final SortedMap<Long, List<GameWindow>> startTimes = new TreeMap<>();
final SortedMap<Long, List<GameWindow>> endTimes = new TreeMap<>();

添加一个窗口然后是:

public void addGameWindow(final GameWindow window)
{
    final long startTime = window.startTime();
    final long endTime = window.endTime();
    List<GameWindow> list;

    // Insert in start times
    list = startTimes.get(startTime);
    if (list == null) {
        list = new ArrayList<>();
        startTimes.put(startTime, list);
    }
    list.add(window);

    // Insert in end times
    list = endTimes.get(endTime);
    if (list == null) {
        list = new ArrayList<>();
        endTimes.put(endTime, list);
    }
    list.add(window);
}

然后查看窗口给定的时间是:

public List<GameWindow> getWindowsForTime(final long time)
{
    // Submap of start times where the time is lower than or equal to
    // the requested time
    final SortedMap<Long, List<GameWindow>> validStartTimes 
        = startTimes.headMap(time);
    // Submap of end times where the time is greater than or equal to
    // the requested time
    final SortedMap<Long, List<GameWindow>> validEndTimes 
        = endTimes.tailMap(time);

    // Why GameWindow must implement equals and hashCode
    final Set<GameWindow> startSet = new HashSet<>();
    final Set<GameWindow> endSet = new HashSet<>();

    // Insert into the start set all game windows whose start time
    // is less than or equal to the requested time
    for (final List<GameWindow> list: startTimes.headMap(time).values())
        startSet.addAll(list);

    // Insert into the end set all game windows whose end time
    // is greater than or equal to the requested time
    for (final List<GameWindow> list: endTimes.tailMap(time).values())
        endSet.addAll(list);

    // Only retain the intersection of both sets
    startSet.retainAll(endSet);

    // Return the result
    return new ArrayList<>(startSet);
}

两个关键要素是:

  • SortedMap.{tail,end}Map()立即过滤掉所有开始时间或结束时间不合法的窗口;
  • HashSet用于只保留开始时间和结束时间都合法的窗口的交集;因此GameWindow 实现hashCode()equals() 的重要性。

【讨论】:

    猜你喜欢
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2011-10-28
    • 2012-04-17
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    相关资源
    最近更新 更多