【问题标题】:Iterating through a LinkedHashMap in reverse order以相反的顺序遍历 LinkedHashMap
【发布时间】:2011-11-02 12:10:50
【问题描述】:

我有一个 LinkedHashMap:

LinkedHashMap<String, RecordItemElement>

我需要从给定键的位置向后迭代。因此,如果给我第 10 个项目的键,我需要向后遍历哈希图 9、8、7 等。

【问题讨论】:

  • 你知道所有物品的钥匙吗?
  • 我愿意。建议我迭代一次,添加到列表中,然后使用它们作为键向后迭代?假设这会工作
  • 我假设您只想在此处以“插入顺序”反向迭代,或者您是否想要基于某种自然顺序的真正排序?另见stackoverflow.com/a/1936472/32453

标签: java hashmap linkedhashmap


【解决方案1】:

这个问题需要一个反向顺序的 LinkedHashMap,一些答案建议使用 TreeSet 但这会根据键重新排序地图。

这个解决方案允许迭代原始的 LinkedHashMap 而不是新的 ArrayList,正如已经提出的那样:

List<String> reverseOrderedKeys = new ArrayList<String>(linkedHashMap.keySet());
Collections.reverse(reverseOrderedKeys);
for (String key : reverseOrderedKeys) {
    RecordItemElement line = linkedHashMap.get(key);
}

【讨论】:

    【解决方案2】:

    哈希映射:

    HashMap<Integer, String> map = new HashMap<Integer, String>();
    

    反向迭代值:

    ListIterator<Sprite> iterator = new ArrayList<String>(map.values()).listIterator(map.size());
    while (iterator.hasPrevious()) String value = iterator.previous();
    

    对键进行反向迭代:

    ListIterator<Integer> iterator = new ArrayList(map.keySet()).listIterator(map.size());
    while (iterator.hasPrevious()) Integer key = iterator.previous();
    

    对两者进行反向迭代:

    ListIterator<Map.Entry<Integer, String>> iterator = new ArrayList<Map.Entry<Integer, String>>(map.entrySet()).listIterator(map.size());
    while (iterator.hasPrevious()) Map.Entry<Integer, String> entry = iterator.previous();
    

    【讨论】:

      【解决方案3】:

      您不必遍历它。但是将钥匙拔下并将其存储在列表中会很方便。这是您可以进行 indexOf() 类型操作的唯一方法。

      List<String> keyList = new ArrayList<String>(map.keySet());
      // Given 10th element's key
      String key = "aKey";
      int idx = keyList.indexOf(key);
      for ( int i = idx ; i >= 0 ; i-- ) 
       System.out.println(map.get(keyList.get(i)));
      

      【讨论】:

      • 而不是 keyList.indexOf(...) 使用 listIterator 与位置。并使用 previous() 进行迭代
      • 使用 keyList.size()-1 代替 keyList.indexOf(...)
      • @Kal 你的解的运算是O(n),还好..可怕
      • 这样做会通过复制密钥集产生不必要的开销。考虑使用 TreeMap。
      • LinkedHashMap#keySet() 返回一个由LinkedKeySet 支持的Set,这是一个具有包本地可见性的嵌套类。迭代顺序由其Spliterator 定义,其顺序与映射条目的顺序相同。所以,在这种情况下,订单是有保证的。
      【解决方案4】:
      new LinkedList(linkedHashMap.keySet()).descendingIterator();
      

      【讨论】:

        【解决方案5】:

        使用“user22745008”解决方案和带有一些泛型的labdas,您可以获得一个非常简洁的解决方案:

          public static <T, Q> LinkedHashMap<T, Q> reverseMap(LinkedHashMap<T, Q> toReverse)
          {
              LinkedHashMap<T, Q> reversedMap = new LinkedHashMap<>();
              List<T> reverseOrderedKeys = new ArrayList<>(toReverse.keySet());
              Collections.reverse(reverseOrderedKeys);
              reverseOrderedKeys.forEach((key)->reversedMap.put(key,toReverse.get(key)));
              return reversedMap;
            }
        

        【讨论】:

          【解决方案6】:

          这是一个老问题,但我认为它缺乏采用更新方法的答案。以下使用 Java 9 功能:

          Deque<Map.Entry<String, RecordItemElement>> top = map.entrySet().stream()
                  .takeWhile(e -> !givenKey.equals(e.getKey()))
                  .collect(Collectors.toCollection(ArrayDeque::new));
          

          上面的代码流式传输地图的条目集,保留条目直到找到与给定键相等的键。然后,将条目收集到ArrayDeque

          但缺少一个细节。根据您是否需要与给定键匹配的条目也包含在结果中,您可能需要手动将其添加到双端队列。如果您不想添加它,那么您就完成了。否则,只需执行:

          top.add(Map.entry(givenKey, map.get(givenKey)));
          

          现在,要以相反的顺序迭代Deque,只需使用它的descendingIterator()

          Iterator<Map.Entry<String, RecordItemElement>> descIt = top.descendingIterator();
          

          值得一提的是,这种方法只有在流是顺序的情况下才有效。无论如何,在这里使用并行流不会有任何收获。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-06
            • 2021-08-17
            • 2018-03-08
            • 2011-01-07
            相关资源
            最近更新 更多