LinkedHashMap中获取最后一个key或value的最便捷方法是什么?

7
LinkedHashMap的描述中提到“它维护一个双向链表,遍历所有条目”,那么我想知道如何获取最后一个输入的条目或键?我能否自信地将.values()向下转换为LinkedList来获取该双向链表并使用.getLast()呢?还是它是Java集合的其他实例?如果可能的话,我想坚持使用java.util

1
方法values()不返回List<>视图或LinkedList<>视图;而是返回一个Collection<>视图。实际返回的类型是一个名为Values的私有类的实例,该类扩展了AbstractCollection<> - Swaranga Sarma
1
你可以创建一个自定义类,用于存储最后输入的元素... - user684934
bdares,您是否想将此评论作为答案发布?如果您这样做,我会接受它作为答案,因为这是我最喜欢的。 - Navigateur
似乎在java.util中不可能实现(无需反射),但请参见https://dev59.com/cHI-5IYBdhLWcg3wR2Jr#1936472。 - rogerdpack
可能是Java LinkedHashMap获取第一个或最后一个条目的重复问题。 - Brett Okken
4个回答

1

是的,您可以获取最后一个元素。但是您需要查看其他人的建议,以获取由values()返回的Collection<V>的最后一个元素。

我在源代码中检查了返回的值确实按预期顺序排列: LinkedListMap.values()返回的AbstactCollection<V>由一个Iterator<V>支持,该迭代器本身直接链接到Iterator<K>上。显然,Iterator<K>是使用有序双向链表实现的。


值得指出的是,文档中没有任何内容表明迭代LinkedHashMap的值时保证遵循映射的插入顺序。 - Max

0

不好意思,你不能这样做。

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

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

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

letLast() => 你是不是想说 getLast() ? - null

0

更新:我之前的回答是错误的。如果不修改默认行为,您无法这样做!请看下面的原因。


如何获取最后一个输入或键入的条目?
从LinkedHashMap的API描述中,您可以阅读到:
结构修改是添加或删除一个或多个映射的任何操作,或者在访问有序链接哈希映射的情况下影响迭代顺序。在插入有序链接哈希映射中,仅更改已包含在映射中的键关联的值不是结构修改。在访问有序链接哈希映射中,仅使用get查询映射是结构修改。
那么这一切意味着什么呢?
- 访问有序 - 每次进行put或get时,元素的顺序都会改变。 - 插入有序 - 在插入元素(第一次)时,它们被添加到最后。
例如:
map.put(1, 1); 
map.put(2, 2); 
map.put(1, 10);
System.out.println(map);

...将使用插入排序打印{1=10, 2=2},并使用访问顺序打印{2=2, 1=10}。问题在于,使用访问顺序时,如果进行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)的时间获取它。 - AlikElzin-kilaka

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接