问题
我使用了LinkedHashMap
,因为重要的是键在 Map 中输入的顺序。
但是现在我想首先获得key的值(第一个输入的条目)或者最后一个。
应该有类似first()
和last()
之类的方法吗?
我是否需要一个迭代器来获取第一个键入口?这就是为什么我用了LinkedHashMap
!
谢谢!
#1 热门回答(120 赞)
LinkedHashMap
的语义仍然是Map的语义,而不是aLinkedList
的语义。它保留了插入顺序,是的,但这是一个实现细节,而不是其界面的一个方面。
获得"第一"条目的最快方式仍然是entrySet().iterator().next()
。获取"最后"条目是可能的,但是需要通过调用.next()
迭代整个条目集,直到达到最后一个.while (iterator.hasNext()) { lastElement = iterator.next() }
编辑:但是,如果你愿意超越JavaSE API,Apache Commons Collections有自己的LinkedMap
实现,它有像firstKey
和lastKey
这样的方法,可以满足你的需求。界面相当丰富。
#2 热门回答(12 赞)
你可以尝试做类似的事情(获得最后一个条目):
linkedHashMap.entrySet().toArray()[linkedHashMap.size() -1];
这是O(N):)
#3 热门回答(8 赞)
LinkedHashMap
当前实现(Java 8)跟踪其尾部。如果考虑性能和/或 Map 大小,你可以通过反射访问该字段。
由于实施可能会发生变化,因此也可能采用后备策略。如果抛出异常,你可能希望记录某些内容,因此你知道实现已更改。
它可能看起来像:
public static <K, V> Entry<K, V> getFirst(Map<K, V> map) {
if (map.isEmpty()) return null;
return map.entrySet().iterator().next();
}
public static <K, V> Entry<K, V> getLast(Map<K, V> map) {
try {
if (map instanceof LinkedHashMap) return getLastViaReflection(map);
} catch (Exception ignore) { }
return getLastByIterating(map);
}
private static <K, V> Entry<K, V> getLastByIterating(Map<K, V> map) {
Entry<K, V> last = null;
for (Entry<K, V> e : map.entrySet()) last = e;
return last;
}
private static <K, V> Entry<K, V> getLastViaReflection(Map<K, V> map) throws NoSuchFieldException, IllegalAccessException {
Field tail = map.getClass().getDeclaredField("tail");
tail.setAccessible(true);
return (Entry<K, V>) tail.get(map);
}