【问题标题】:Iterate to find a Map entry at an index?迭代以在索引处查找 Map 条目?
【发布时间】:2016-07-24 21:22:33
【问题描述】:

我有一个 LinkedHashMap。我想在索引 N 处获取 Foo。除了迭代直到找到它之外,还有更好的方法吗?:

int target = N;
int index = 0;
for (Map.Entry<String, Foo> it : foos.entrySet()) {
    if (index == target) {
        return it.getValue();
    }
    index++;
}

对于某些操作,我必须通过索引从地图中获取随机元素大约 50 次。该地图将包含大约 20 个项目。

谢谢

【问题讨论】:

    标签: java


    【解决方案1】:
    List<Entry<String,Foo>> randAccess = new ArrayList<Entry<String,Foo>>(foos.entrySet());
    

    那么对于具有 O(1) 访问权限的索引 N...

    randAccess.get(N)
    

    【讨论】:

    • 您已经花费了 O(N) 时间来创建地图中所有键的副本。如果任何内容被插入到地图中,您的副本将不会被更新。 初始复制后的连续查询只需 O(1).
    【解决方案2】:

    @Mark 的解决方案是正确的。我只想指出,地图(任何类型)中条目的偏移量(位置)并不稳定。每次添加或删除条目时,剩余条目的偏移量可能会改变。对于 HashMap 或 LinkedHashMap,您无​​法知道哪个条目的偏移量会改变。

    • 对于常规 HashMap,单个插入显然可以“随机化”条目偏移量。
    • 对于LinkedHashMap,条目的顺序是稳定的,实际的条目偏移量是不稳定的。

    偏移量的不稳定性以及在给定偏移量处查找条目对于所有标准映射实现而言代价高昂的事实是Map 接口不提供get(int offset) 方法的原因。这也应该暗示算法需要做这种事情不是一个好主意。

    【讨论】:

    • 我想我可能有相同的评论,除了 OP 使用 LinkedHashMap 保持与迭代的插入顺序相对应的条目的链表......因此迭代的顺序是稳定的随着时间的推移......不是吗?
    【解决方案3】:

    @Mark 解决方案的简化... 您只需要这些值,因此每次更改 foos Map 中的值时,也会更新一个数组。

    Map<String, Foo> foos =;
    Foo[] fooValues = {};
    
    foos.put(foos.name(), foo);
    fooValues = foos.values().toArray(new Foo[foos.size()]);
    
    // later
    Foo foo = fooValues[N];
    

    【讨论】:

      【解决方案4】:

      Guava 库可以在这种情况下提供帮助:

      public static <T> T com.google.common.collect.Iterables.get(Iterable<T> iterable, int position)
      

      see javadoc: Iterables.get

      对于您的情况,代码可以是这样的:

      Iterables.get(foos.values(), N);
      

      【讨论】:

        猜你喜欢
        • 2020-11-15
        • 1970-01-01
        • 2015-04-03
        • 1970-01-01
        • 2014-11-10
        • 2021-04-28
        • 1970-01-01
        • 2023-01-27
        • 1970-01-01
        相关资源
        最近更新 更多