问题

我使用了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实现,它有像firstKeylastKey这样的方法,可以满足你的需求。界面相当丰富。


#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);
}

原文链接