Java LinkedHashMap获取第一个或最后一个条目

我已经使用LinkedHashMap因为它在键入地图的顺序是重要的。

但是现在我想要把钥匙的价值放在第一位(第一个input的项目)或最后一个。

应该有像first()last()类的方法吗?

我是否需要有一个迭代器才能获得第一个键入? 这就是为什么我使用LinkedHashMap

谢谢!

LinkedHashMap的语义仍然是Map的语义,而不是LinkedList的语义。 它保留了插入顺序,是的,但这是一个实现细节,而不是其接口的一个方面。

获得“第一个”条目的最快方法仍然是entrySet().iterator().next() 。 获得“最后”条目是可能的,但是需要通过调用.next()遍历整个条目集合,直到达到最后。 while (iterator.hasNext()) { lastElement = iterator.next() }

编辑 :但是,如果您愿意超越JavaSE API,那么Apache Commons Collections有自己的LinkedMap实现,它具有像firstKeylastKey这样的方法,可以执行您正在寻找的任务。 界面相当丰富。

获取LinkedHashMap的第一个和最后一个入口的另一种方法是使用Set接口的“toArray”方法。

但我认为迭代条目集合中的条目并获得第一个和最后一个条目是更好的方法。

数组方法的用法会导致警告窗体“…需要不受限制的转换以符合…” ,这是无法修复的(但只能通过使用注释@SuppressWarnings(“unchecked”)]来禁止。

下面是一个小例子来演示“toArray”方法的用法:

 public static void main(final String[] args) { final Map<Integer,String> orderMap = new LinkedHashMap<Integer,String>(); orderMap.put(6, "Six"); orderMap.put(7, "Seven"); orderMap.put(3, "Three"); orderMap.put(100, "Hundered"); orderMap.put(10, "Ten"); final Set<Entry<Integer, String>> mapValues = orderMap.entrySet(); final int maplength = mapValues.size(); final Entry<Integer,String>[] test = new Entry[maplength]; mapValues.toArray(test); System.out.print("First Key:"+test[0].getKey()); System.out.println(" First Value:"+test[0].getValue()); System.out.print("Last Key:"+test[maplength-1].getKey()); System.out.println(" Last Value:"+test[maplength-1].getValue()); } // the output geneated is : First Key:6 First Value:Six Last Key:10 Last Value:Ten 

你可以尝试做一些像(获得最后一个条目):

 linkedHashMap.entrySet().toArray()[linkedHashMap.size() -1]; 

这是O(N):)

LinkedHashMap当前实现(Java 8)跟踪其尾部。 如果性能问题和/或地图尺寸较大,则可以通过reflection访问该字段。

因为实施可能会改变,所以也可以有一个备用策略。 如果抛出一个exception,你可能想logging一些东西,所以你知道实现已经改变了。

它可能看起来像:

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

这有点脏,但是你可以重写LinkedHashMap的removeEldestEntry方法,它可能适合你做一个私人的匿名成员:

 private Splat eldest = null; private LinkedHashMap<Integer, Splat> pastFutures = new LinkedHashMap<Integer, Splat>() { @Override protected boolean removeEldestEntry(Map.Entry<Integer, Splat> eldest) { eldest = eldest.getValue(); return false; } }; 

所以你永远可以得到你eldest成员的第一个条目。 每次执行put时都会更新。

也应该很容易覆盖put和设置youngest

  @Override public Splat put(Integer key, Splat value) { youngest = value; return super.put(key, value); } 

当你开始删除条目的时候,它全部崩溃; 还没有想出一个办法来克服这一点。

这是非常烦人的,你不能以合理的方式获得头部或尾部…

我build议使用具有firstKey()lastKey()方法的ConcurrentSkipListMap

也许是这样的:

 LinkedHashMap<Integer, String> myMap; public String getFirstKey() { String out = null; for (int key : myMap.keySet()) { out = myMap.get(key); break; } return out; } public String getLastKey() { String out = null; for (int key : myMap.keySet()) { out = myMap.get(key); } return out; } 

虽然linkedHashMap不提供任何方法来获取第一个,最后一个或任何特定的对象。

但是它的相当微不足道:

  • map orderMap = new LinkedHashMap();
    Set al = orderMap.keySet();

现在在对象上使用迭代器; 你可以得到任何对象。

是的,我遇到了同样的问题,但幸运的是,我只需要第一个元素… – 这就是我所做的。

 private String getDefaultPlayerType() { String defaultPlayerType = ""; for(LinkedHashMap.Entry<String,Integer> entry : getLeagueByName(currentLeague).getStatisticsOrder().entrySet()) { defaultPlayerType = entry.getKey(); break; } return defaultPlayerType; } 

如果你还需要最后一个元素 – 我会研究如何扭转你的地图的顺序 – 将它存储在一个临时variables,访问反向地图中的第一个元素(因此这将是你的最后一个元素),杀死临时variables。

下面是关于如何颠倒散列图的顺序的一些很好的答案:

如何在Java中以相反顺序迭代hashmap

如果你从上面的链接使用帮助,请给他们赞成票:)希望这可以帮助一个人。

build议:

 map.remove(map.keySet().iterator().next());