【问题标题】:Most convenient way to get the last key or value in a LinkedHashMap?获取 LinkedHashMap 中最后一个键或值的最方便方法?
【发布时间】:2011-09-03 11:47:47
【问题描述】:

LinkedHashMap 描述说“它维护一个贯穿其所有条目的双向链表”所以我想知道如何获取最后一个条目或输入的键?我可以自信地将.values() 转换为LinkedList 以获得该双向链表并使用其中的.getLast() 吗?还是它是其他 Java 集合的实例?

如果可能的话,我想坚持使用java.util

【问题讨论】:

  • 方法values()不返回List<>视图或LinkedList<>视图;而是返回一个Collection<> 视图。返回的实际类型是一个名为 Values 的私有类的实例,它扩展了 AbstractCollection<>
  • 您可以创建一个自定义类来存储最后输入的元素...
  • bdares,您想将此评论作为答案吗?这是我的最爱,如果你愿意,我会接受它作为答案。
  • 使用 java.util 似乎不可能(没有反射),但请参阅 stackoverflow.com/a/1936472/32453

标签: java key linkedhashmap


【解决方案1】:

是的,你可以得到最后一个元素。但是您必须查看其他人的建议才能获得values() 返回的Collection<V> 的最后一个元素。

我在源代码中检查了返回值确实符合预期的顺序: LinkedListMap.values() 返回的 AbstactCollection<V> 在值上由 Iterator<V> 支持,而值本身直接链接到键上的 Iterator<K>。显然,键上的Iterator<K> 是通过有序双向链表实现的。

【讨论】:

  • 值得指出的是,文档中没有任何内容表明对 LinkedHashMap 的值的迭代可以保证尊重地图的插入顺序。
【解决方案2】:

不,抱歉,你不能。

“维护的双向链表”不是任何 java.util.LinkedList 类型或其他集合。它是在 LinkedHashMap 和 LinkedHashMap.Entry 类中手动实现的。

您只能从values() 构建LinkedList,然后使用letLast()

Foo last = new LinkedList<Foo>(myLinkedHashMap.values()).getLast();

【讨论】:

  • letLast() => 你的意思是getLast() 吗?
【解决方案3】:

更新:我之前的回答是错误的。如果不修改默认行为,您将无法做到这一点!见下文为什么。


..如何获取最后输入的条目或输入的键?

LinkedHashMap的API描述可以读到:

结构修改是添加或删除一个或多个映射的任何操作,或者在访问排序的链接哈希映射的情况下,会影响迭代顺序。在 insertion-ordered 链接哈希映射中,仅更改与映射中已包含的键关联的值并不是结构修改。在 access-ordered 链接的哈希映射中,仅使用 get 查询映射是一种结构修改。

那么这一切意味着什么?

  • access-ordered - 每次您执行 putget 时,元素的顺序都会发生变化
  • insertion-ordered - 插入元素时(第一次)它们最后添加

例如:

map.put(1, 1); 
map.put(2, 2); 
map.put(1, 10);
System.out.println(map);

... 将打印带有 insertion-ordered{1=10, 2=2} 和带有 *access-ordered' 的 {2=2, 1=10}。问题在于使用access-ordered,当然如果您执行get 操作,顺序也会发生变化。


如何解决

那么...如何解决。那么LinkedHashMap不能直接使用。所以你可以包装它(不要关心老生常谈的名字)并覆盖 putputAll 方法,以便他们在放回地图之前先从地图中删除密钥!

class BestLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    @Override
    public V put(K key, V value) {
        V last = super.remove(key);
        super.put(key, value);
        return last;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for (K key : m.keySet())
            super.remove(key);

        super.putAll(m);
    }
}

然后要获取最后一个元素,请执行以下操作:

  • 将输出包装在 LinkedList 实现中:

    V v = new LinkedList<V>(map.values()).getLast();
    
  • toArray()方式:

    Collection<V> values = map.values();
    V v = values.toArray(new V[0])[values.size() - 1];
    
  • 使用迭代器迭代到最后一个元素:

    Iterator<V> it = values.iterator();
    V last = null;
    while (it.hasNext())
        last = it.next();
    

【讨论】:

  • 此解决方案遍历所有值,而不是在 O(1) 中获取它 - 就像它是一个双链表一样。
【解决方案4】:

我已经“扩展”了 Jdk LinkedHashMap 以允许这样做,你可以看看:LinkedHashMapEx.java

【讨论】:

    猜你喜欢
    • 2010-12-28
    • 2018-10-14
    • 1970-01-01
    • 2021-09-28
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    相关资源
    最近更新 更多