如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
当前回答
如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
如果循环键的效率是应用程序的优先事项,那么选择一个Map实现,以您所需的顺序维护键。
元素的顺序是否取决于我对接口的特定映射实现?
是的,绝对。
一些Map实现承诺一定的迭代顺序,而其他的则没有。Map的不同实现维护键值对的不同顺序。
请参见我创建的总结了与Java11捆绑的各种Map实现的表。具体来说,请注意迭代顺序列。单击/轻按以缩放。
您可以看到,有四个Map实现维护一个顺序:
树图并发跳过列表映射链接的哈希映射EnumMap(枚举映射)
NavigableMap界面
其中两个实现NavigableMap接口:TreeMap&ConcurrentSkipListMap。
旧的SortedMap界面被新的NavigableMap界面有效地取代。但您可能会发现第三方实现仅实现旧接口。
自然秩序
如果您想要一个按键的“自然顺序”排列其对的Map,请使用TreeMap或ConcurrentSkipListMap。术语“自然顺序”是指实现Comparable的键类。compareTo方法返回的值用于排序中的比较。
自定义订单
如果要为键指定自定义排序例程以用于维护排序顺序,请传递适合于键类的Comparator实现。使用TreeMap或ConcurrentSkipListMap,传递比较器。
原始插入顺序
如果您希望映射对保持在它们插入映射的原始顺序,请使用LinkedHashMap。
枚举定义顺序
如果使用诸如DayOfWeek或Month之类的枚举作为键,请使用EnumMap类。这个类不仅被高度优化以使用很少的内存并且运行非常快,它还按照枚举定义的顺序维护您的对。例如,对于DayOfWeek,DayOfWeek.MONDAY的键将在迭代时首先找到,DayOfWeek.SUNDAY的密钥将是最后一个。
其他注意事项
在选择Map实现时,还应考虑:
NULLs。某些实现禁止/接受NULL作为键和/或值。并发性。如果要跨线程操作映射,则必须使用支持并发的实现。或者使用Collections::synchronizedMap包装映射(不太可取)。
以上图表中涵盖了这两个考虑因素。
其他回答
我用以下代码将地图数据复制到另一个地图:
HashMap product =(HashMap)shopping_truck.get(i);
HashMap tmp = new HashMap();
for (Iterator it = product.entrySet().iterator(); it.hasNext();) {
Map.Entry thisEntry = (Map.Entry) it.next();
tmp.put(thisEntry.getKey(), thisEntry.getValue());
}
这些都是迭代HashMap的所有可能方法。
HashMap<Integer,String> map=new HashMap<Integer,String>();
map.put(1,"David"); //Adding elements in Map
map.put(2,"John");
map.put(4,"Samyuktha");
map.put(3,"jasmin");
System.out.println("Iterating Hashmap...");
//way 1 (java 8 Method)
map.forEach((key, value) -> {
System.out.println(key+" : "+ value);
});
//way 2 (java 7 Method)
for(Map.Entry me : map.entrySet()){
System.out.println(me.getKey()+" "+me.getValue());
}
//way 3 (Legacy way to iterate HashMap)
Iterator iterator = map.entrySet().iterator();//map.keySet().iterator()
while (iterator.hasNext())
{
Map.Entry me =(Map.Entry)iterator.next();
System.out.println(me.getKey()+" : "+ me.getValue());
}
}
您可以使用泛型:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Integer, Integer> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
迭代地图非常简单。
for(Object key: map.keySet()){
Object value= map.get(key);
//Do your stuff
}
例如,您有一个Map<String,int>数据;
for(Object key: data.keySet()){
int value= data.get(key);
}
在地图上迭代的典型代码是:
Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
String key = entry.getKey();
Thing thing = entry.getValue();
...
}
HashMap是规范映射实现,不做任何保证(或者,如果不对其执行任何变异操作,则不应更改顺序)。SortedMap将根据键的自然顺序或Comparator(如果提供)返回条目。LinkedHashMap将按照插入顺序或访问顺序返回条目,具体取决于它的构造方式。EnumMap以键的自然顺序返回条目。
(更新:我认为这不再是真的。)注意,IdentityHashMap entrySet迭代器目前有一个特殊的实现,它为entrySet中的每个项返回相同的Map.Entry实例!然而,每次新迭代器推进Map.Entry时都会更新。