如何有效地迭代JavaMap中的每个条目?

如果我有一个在Java中实现Map接口的对象,并且我希望遍历其中包含的每一对,那么遍历map的最有效方法是什么?

元素的排序是否取决于接口的特定map实现?

3119563 次浏览

是的,顺序取决于具体的Map实现。

@ScArcher2有更优雅Java1.5语法.在1.4中,我会这样做:

Iterator entries = myMap.entrySet().iterator();while (entries.hasNext()) {Entry thisEntry = (Entry) entries.next();Object key = thisEntry.getKey();Object value = thisEntry.getValue();// ...}
Map<String, String> map = ...for (Map.Entry<String, String> entry : map.entrySet()) {System.out.println(entry.getKey() + "/" + entry.getValue());}

Java10+:

for (var entry : map.entrySet()) {System.out.println(entry.getKey() + "/" + entry.getValue());}

理论上,最有效的方法将取决于Map的实现。官方的方法是调用map.entrySet(),它返回一组Map.Entry,每个都包含一个键和值(entry.getKey()entry.getValue())。

在一个特殊的实现中,使用map.keySet()map.entrySet()还是其他东西可能会有所不同。但我想不出为什么有人会这样写。很可能它对你所做的性能没有影响。

是的,顺序将取决于实现-以及(可能)插入顺序和其他难以控制的因素。

[编辑]我最初写了valueSet(),但当然entrySet()实际上是答案。

迭代map的典型代码是:

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以键的自然顺序返回条目。

(更新:我认为这不再是真的。)注意,IdentityHashMapentrySet迭代器目前有一个特殊的实现,它为entrySet中的每个项目返回相同的Map.Entry实例!但是,每次新迭代器前进时,Map.Entry都会更新。

这是一个两部分的问题:

如何遍历Map的条目-@ScArcher2完美地拥有回答

迭代的顺序是什么-如果你只是使用Map,那么严格来说,有无订购保证。所以你不应该真正依赖任何实现给出的顺序。然而,#1接口扩展了Map并提供了你正在寻找的东西-实现总是会给出一致的排序顺序。

#0是另一个有用的扩展-这是一个SortedMap,它带有额外的方法来通过它们在键集中的有序位置查找条目。因此,这可能首先消除了迭代的需要-您可能能够在使用higherEntrylowerEntryceilingEntryfloorEntry方法后找到特定的entrydescendingMap方法甚至为您提供了反转遍历顺序的显式方法。

仅供参考,如果您只对映射的键/值感兴趣而对其他键/值不感兴趣,您也可以使用map.keySet()map.values()

正确的方法是使用公认的答案,因为它是最有效的。我发现下面的代码看起来更干净。

for (String key: map.keySet()) {System.out.println(key + "/" + map.get(key));}

使用迭代器和泛型的示例:

Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();while (entries.hasNext()) {Map.Entry<String, String> entry = entries.next();String key = entry.getKey();String value = entry.getValue();// ...}

试试Java1.4:

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){
Entry entry = (Entry) entries.next();
System.out.println(entry.getKey() + "/" + entry.getValue());
//...}
public class abcd{public static void main(String[] args){Map<Integer, String> testMap = new HashMap<Integer, String>();testMap.put(10, "a");testMap.put(20, "b");testMap.put(30, "c");testMap.put(40, "d");for (Integer key:testMap.keySet()) {String value=testMap.get(key);System.out.println(value);}}}

public class abcd {public static void main(String[] args){Map<Integer, String> testMap = new HashMap<Integer, String>();testMap.put(10, "a");testMap.put(20, "b");testMap.put(30, "c");testMap.put(40, "d");for (Entry<Integer, String> entry : testMap.entrySet()) {Integer key=entry.getKey();String value=entry.getValue();}}}

对于Eclipse集合,您将在#1接口上使用forEachKeyValue方法,该方法由MutableMapImmutableMap接口及其实现继承。

MutableBag<String> result = Bags.mutable.empty();MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");map.forEachKeyValue((key, value) -> result.add(key + value));Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

使用匿名内部类,您可以编写如下代码:

final MutableBag<String> result = Bags.mutable.empty();MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");map.forEachKeyValue(new Procedure2<Integer, String>(){public void value(Integer key, String value){result.add(key + value);}});Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

备注:我是Eclipse集合的提交者。

是的,正如许多人同意的那样,这是迭代Map的最佳方式。

但是如果地图是null,就有机会抛出nullpointerexception。不要忘记放null。签到。

                                                 ||- - - -||for (Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey();Object value = entry.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());}

在Java8中,您可以使用新的lambdas功能进行清洁和快速操作:

 Map<String,String> map = new HashMap<>();map.put("SomeKey", "SomeValue");map.forEach( (k,v) -> [do something with key and value] );
// such asmap.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));

kv的类型将由编译器推断,不再需要使用Map.Entry

轻而易举!

如果你有一个通用的无类型映射,你可以使用:

Map map = new HashMap();for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {System.out.println(entry.getKey() + "/" + entry.getValue());}

有几种方法可以迭代映射。请参考以下代码。

当您使用迭代器接口迭代映射时,您必须使用Entry<K,V>entrySet()

它看起来像这样:

    import java.util.*;import java.util.HashMap;import java.util.Iterator;import java.util.Map;
public class IteratMapDemo{
public static void main(String arg[]){Map<String, String> mapOne = new HashMap<String, String>();mapOne.put("1", "January");mapOne.put("2", "February");mapOne.put("3", "March");mapOne.put("4", "April");mapOne.put("5", "May");mapOne.put("6", "June");mapOne.put("7", "July");mapOne.put("8", "August");mapOne.put("9", "September");mapOne.put("10", "Octomber");mapOne.put("11", "November");mapOne.put("12", "December");
Iterator it = mapOne.entrySet().iterator();while(it.hasNext()){Map.Entry me = (Map.Entry) it.next();//System.out.println("Get Key through While loop = " + me.getKey());}for(Map.Entry<String, String> entry:mapOne.entrySet()){//System.out.println(entry.getKey() + "=" + entry.getValue());}
for (Object key : mapOne.keySet()) {System.out.println("Key: " + key.toString() + " Value: " +mapOne.get(key));}}}

在Map中,可以迭代keys和/或values和/或both (e.g., entrySet)取决于自己感兴趣的in_比如:

  1. 遍历map的#0

     Map<String, Object> map = ...;
    for (String key : map.keySet()) {//your Business logic...}
  2. 遍历map的#0

     for (Object value : map.values()) {//your Business logic...}
  3. 遍历map的#0

     for (Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey();Object value = entry.getValue();//your Business logic...}

此外,有3种不同的方法来迭代HashMap。它们如下所示:

//1.for (Map.Entry entry : hm.entrySet()) {System.out.print("key,val: ");System.out.println(entry.getKey() + "," + entry.getValue());}
//2.Iterator iter = hm.keySet().iterator();while(iter.hasNext()) {Integer key = (Integer)iter.next();String val = (String)hm.get(key);System.out.println("key,val: " + key + "," + val);}
//3.Iterator it = hm.entrySet().iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();Integer key = (Integer)entry.getKey();String val = (String)entry.getValue();System.out.println("key,val: " + key + "," + val);}

有几种方法可以遍历map。

下面通过在map中存储一百万个键值对来比较它们对存储在map中的公共数据集的性能,并将遍历map。

1)对每个循环使用entrySet() in

for (Map.Entry<String,Integer> entry : testMap.entrySet()) {entry.getKey();entry.getValue();}

50毫秒

2)对每个循环使用keySet() in

for (String key : testMap.keySet()) {testMap.get(key);}

76毫秒

3)使用entrySet()和迭代器

Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();while(itr1.hasNext()) {Map.Entry<String,Integer> entry = itr1.next();entry.getKey();entry.getValue();}

50毫秒

4)使用keySet()和迭代器

Iterator itr2 = testMap.keySet().iterator();while(itr2.hasNext()) {String key = itr2.next();testMap.get(key);}

75毫秒

我提到了#0

    Iterator iterator = map.entrySet().iterator();while (iterator.hasNext()) {Map.Entry element = (Map.Entry)it.next();LOGGER.debug("Key: " + element.getKey());LOGGER.debug("value: " + element.getValue());}

Java8:

您可以使用lambda表达式:

myMap.entrySet().stream().forEach((entry) -> {Object currentKey = entry.getKey();Object currentValue = entry.getValue();});

有关更多信息,请关注这个

我使用此代码将地图的数据复制到另一个:

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

它并没有完全回答OP的问题,但可能对找到此页面的其他人有用:

如果你只需要值而不是键,你可以这样做:

Map<Ktype, Vtype> myMap = [...];for (Vtype v: myMap.values()) {System.out.println("value: " + v);}

KtypeVtype是伪代码。

这是一个泛型类型安全方法,可以调用它来转储任何给定的Map

import java.util.Iterator;import java.util.Map;
public class MapUtils {static interface ItemCallback<K, V> {void handler(K key, V value, Map<K, V> map);}
public static <K, V> void forEach(Map<K, V> map, ItemCallback<K, V> callback) {Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
while (it.hasNext()) {Map.Entry<K, V> entry = it.next();
callback.handler(entry.getKey(), entry.getValue(), map);}}
public static <K, V> void printMap(Map<K, V> map) {forEach(map, new ItemCallback<K, V>() {@Overridepublic void handler(K key, V value, Map<K, V> map) {System.out.println(key + " = " + value);}});}}

示例

下面是它的使用示例。请注意,Map的类型是由方法推断的。

import java.util.*;
public class MapPrinter {public static void main(String[] args) {List<Map<?, ?>> maps = new ArrayList<Map<?, ?>>() {private static final long serialVersionUID = 1L;{add(new LinkedHashMap<String, Integer>() {private static final long serialVersionUID = 1L;{put("One", 0);put("Two", 1);put("Three", 3);}});
add(new LinkedHashMap<String, Object>() {private static final long serialVersionUID = 1L;{put("Object", new Object());put("Integer", new Integer(0));put("Double", new Double(0.0));}});}};
for (Map<?, ?> map : maps) {MapUtils.printMap(map);System.out.println();}}}

产出

One = 0Two = 1Three = 3
Object = java.lang.Object@15db9742Integer = 0Double = 0.0

我相信这是最简单的方法…

/* For example, this could be a map object */Map<String, Integer> MAP = new Map<>();
// Do something like put keys/value pairs into the map, etc...MAP.put("Denver", 35);MAP.put("Patriots", 14);
/* Then, simply use a for each loop like this to iterate */for (Object o : MAP.entrySet()) {Map.Entry pair = (Map.Entry) o;// Do whatever with the pair here (i.e. pair.getKey(), or pair.getValue();}

如果您通过Map进行迭代的原因是对值进行操作并写入结果Map。我建议使用googleguavaMaps类中的transform-方法。

import com.google.common.collect.Maps;

Maps添加到导入后,您可以在地图上使用Maps.transformValuesMaps.transformEntries,如下所示:

public void transformMap(){Map<String, Integer> map = new HashMap<>();map.put("a", 2);map.put("b", 4);
Map<String, Integer> result = Maps.transformValues(map, num -> num * 2);result.forEach((key, val) -> print(key, Integer.toString(val)));// key=a,value=4// key=b,value=8
Map<String, String> result2 = Maps.transformEntries(map, (key, value) -> value + "[" + key + "]");result2.forEach(this::print);// key=a,value=2[a]// key=b,value=4[b]}
private void print(String key, String val){System.out.println("key=" + key + ",value=" + val);}

Java8

我们有forEach方法接受lambda表达式。我们还有 API。考虑一个映射:

Map<String,String> sample = new HashMap<>();sample.put("A","Apple");sample.put("B", "Ball");

遍历键:

sample.keySet().forEach((k) -> System.out.println(k));

遍历值:

sample.values().forEach((v) -> System.out.println(v));

遍历条目(使用foreach和Streams):

sample.forEach((k,v) -> System.out.println(k + ":" + v));sample.entrySet().stream().forEach((entry) -> {Object currentKey = entry.getKey();Object currentValue = entry.getValue();System.out.println(currentKey + ":" + currentValue);});

流的优点是它们可以在我们想要的情况下轻松并行化。我们只需要使用parallelStream()代替上面的stream()

forEachOrdered vsforEach与流?forEach不遵循遭遇顺序(如果定义了),并且本质上是不确定的,就像forEachOrdered一样。所以forEach不能保证顺序会被保留。还要检查这个了解更多。

lambda表达Java8

在Java1.8(Java8)中,通过使用聚合操作(流操作)中的for每个方法(看起来类似于可迭代接口中的迭代器),这变得容易得多。

只需将下面的粘贴语句复制到您的代码中,并将HashMap变量从hm重命名为您的HashMap变量以打印出键值对。

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();/**     Logic to put the Key,Value pair in your HashMap hm*/
// Print the key value pair in one line.
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
// Just copy and paste above line to your code.

下面是我尝试使用lambda表达式的示例代码。这东西太酷了。必须尝试。

HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();Random rand = new Random(47);int i = 0;while(i < 5) {i++;int key = rand.nextInt(20);int value = rand.nextInt(50);System.out.println("Inserting key: " + key + " Value: " + value);Integer imap = hm.put(key, value);if( imap == null) {System.out.println("Inserted");} else {System.out.println("Replaced with " + imap);}}
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
Output:
Inserting key: 18 Value: 5InsertedInserting key: 13 Value: 11InsertedInserting key: 1 Value: 29InsertedInserting key: 8 Value: 0InsertedInserting key: 2 Value: 7Insertedkey: 1 value:29key: 18 value:5key: 2 value:7key: 8 value:0key: 13 value:11

也可以使用分裂者进行相同的操作。

Spliterator sit = hm.entrySet().spliterator();

更新


包括留档链接到Oracle文档。有关lambda的更多信息,请转到此链接,必须阅读聚合操作,对于分裂器,请转到此链接

如果您想按照添加元素的顺序遍历映射,请使用LinkedHashMap而不是Map

这种方法在过去对我很有效:

LinkedHashMap<String,Integer> test=new LinkedHashMap();
test.put("foo",69);test.put("bar",1337);
for(int i=0;i<test.size();i++){System.out.println(test.get(test.keySet().toArray()[i]));}

输出:

691337

为了总结其他答案并将它们与我所知道的结合起来,我找到了10种主要方法(见下文)。此外,我写了一些性能测试(见下文结果)。例如,如果我们想找到map的所有键和值的总和,我们可以这样写:

  1. 使用迭代器地图入口

    long i = 0;Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();while (it.hasNext()) {Map.Entry<Integer, Integer> pair = it.next();i += pair.getKey() + pair.getValue();}
  2. Using foreach and Map.Entry

    long i = 0;for (Map.Entry<Integer, Integer> pair : map.entrySet()) {i += pair.getKey() + pair.getValue();}
  3. Using forEach from Java 8

    final long[] i = {0};map.forEach((k, v) -> i[0] += k + v);
  4. Using keySet and foreach

    long i = 0;for (Integer key : map.keySet()) {i += key + map.get(key);}
  5. Using keySet and iterator

    long i = 0;Iterator<Integer> itr2 = map.keySet().iterator();while (itr2.hasNext()) {Integer key = itr2.next();i += key + map.get(key);}
  6. Using for and Map.Entry

    long i = 0;for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {Map.Entry<Integer, Integer> entry = entries.next();i += entry.getKey() + entry.getValue();}
  7. Using the Java 8 Stream API

    final long[] i = {0};map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
  8. Using the Java 8 Stream API parallel

    final long[] i = {0};map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
  9. Using IterableMap of Apache Collections

    long i = 0;MapIterator<Integer, Integer> it = iterableMap.mapIterator();while (it.hasNext()) {i += it.next() + it.getValue();}
  10. Using MutableMap of Eclipse (CS) collections

    final long[] i = {0};mutableMap.forEachKeyValue((key, value) -> {i[0] += key + value;});

Perfomance tests (mode = AverageTime, system = Windows 8.1 64-bit, Intel i7-4790 3.60 GHz, 16 GB)

  1. For a small map (100 elements), score 0.308 is the best

    Benchmark                          Mode  Cnt  Score    Error  Unitstest3_UsingForEachAndJava8         avgt  10   0.308 ±  0.021  µs/optest10_UsingEclipseMap             avgt  10   0.309 ±  0.009  µs/optest1_UsingWhileAndMapEntry        avgt  10   0.380 ±  0.014  µs/optest6_UsingForAndIterator          avgt  10   0.387 ±  0.016  µs/optest2_UsingForEachAndMapEntry      avgt  10   0.391 ±  0.023  µs/optest7_UsingJava8StreamApi          avgt  10   0.510 ±  0.014  µs/optest9_UsingApacheIterableMap       avgt  10   0.524 ±  0.008  µs/optest4_UsingKeySetAndForEach        avgt  10   0.816 ±  0.026  µs/optest5_UsingKeySetAndIterator       avgt  10   0.863 ±  0.025  µs/optest8_UsingJava8StreamApiParallel  avgt  10   5.552 ±  0.185  µs/op
  2. For a map with 10000 elements, score 37.606 is the best

    Benchmark                           Mode   Cnt  Score      Error   Unitstest10_UsingEclipseMap              avgt   10    37.606 ±   0.790  µs/optest3_UsingForEachAndJava8          avgt   10    50.368 ±   0.887  µs/optest6_UsingForAndIterator           avgt   10    50.332 ±   0.507  µs/optest2_UsingForEachAndMapEntry       avgt   10    51.406 ±   1.032  µs/optest1_UsingWhileAndMapEntry         avgt   10    52.538 ±   2.431  µs/optest7_UsingJava8StreamApi           avgt   10    54.464 ±   0.712  µs/optest4_UsingKeySetAndForEach         avgt   10    79.016 ±  25.345  µs/optest5_UsingKeySetAndIterator        avgt   10    91.105 ±  10.220  µs/optest8_UsingJava8StreamApiParallel   avgt   10   112.511 ±   0.365  µs/optest9_UsingApacheIterableMap        avgt   10   125.714 ±   1.935  µs/op
  3. For a map with 100000 elements, score 1184.767 is the best

    Benchmark                          Mode   Cnt  Score        Error    Unitstest1_UsingWhileAndMapEntry        avgt   10   1184.767 ±   332.968  µs/optest10_UsingEclipseMap             avgt   10   1191.735 ±   304.273  µs/optest2_UsingForEachAndMapEntry      avgt   10   1205.815 ±   366.043  µs/optest6_UsingForAndIterator          avgt   10   1206.873 ±   367.272  µs/optest8_UsingJava8StreamApiParallel  avgt   10   1485.895 ±   233.143  µs/optest5_UsingKeySetAndIterator       avgt   10   1540.281 ±   357.497  µs/optest4_UsingKeySetAndForEach        avgt   10   1593.342 ±   294.417  µs/optest3_UsingForEachAndJava8         avgt   10   1666.296 ±   126.443  µs/optest7_UsingJava8StreamApi          avgt   10   1706.676 ±   436.867  µs/optest9_UsingApacheIterableMap       avgt   10   3289.866 ±  1445.564  µs/op

Graphs (performance tests depending on map size)

Enter image description here

Table (perfomance tests depending on map size)

          100     600      1100     1600     2100test10    0.333    1.631    2.752    5.937    8.024test3     0.309    1.971    4.147    8.147   10.473test6     0.372    2.190    4.470    8.322   10.531test1     0.405    2.237    4.616    8.645   10.707test2     0.376    2.267    4.809    8.403   10.910test7     0.473    2.448    5.668    9.790   12.125test9     0.565    2.830    5.952   13.220   16.965test4     0.808    5.012    8.813   13.939   17.407test5     0.810    5.104    8.533   14.064   17.422test8     5.173   12.499   17.351   24.671   30.403

所有测试都在github上。

           //Functional OprationsMap<String, String> mapString = new HashMap<>();mapString.entrySet().stream().map((entry) -> {String mapKey = entry.getKey();return entry;}).forEach((entry) -> {String mapValue = entry.getValue();});
//IntratorMap<String, String> mapString = new HashMap<>();for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {Map.Entry<String, String> entry = it.next();String mapKey = entry.getKey();String mapValue = entry.getValue();}
//Simple for loopMap<String, String> mapString = new HashMap<>();for (Map.Entry<String, String> entry : mapString.entrySet()) {String mapKey = entry.getKey();String mapValue = entry.getValue();
}

排序将始终取决于特定的map实现。使用Java8,您可以使用以下任何一个:

map.forEach((k,v) -> { System.out.println(k + ":" + v); });

或:

map.entrySet().forEach((e) -> {System.out.println(e.getKey() + " : " + e.getValue());});

结果将是相同的(相同的顺序)。地图支持的entrySet,因此您获得的顺序相同。第二个很方便,因为它允许您使用lambda,例如,如果您只想仅打印大于5的整数对象:

map.entrySet().stream().filter(e-> e.getValue() > 5).forEach(System.out::println);

下面的代码显示了通过LinkedHashMap和普通HashMap(示例)的迭代。你会看到顺序的差异:

public class HMIteration {

public static void main(String[] args) {Map<Object, Object> linkedHashMap = new LinkedHashMap<>();Map<Object, Object> hashMap = new HashMap<>();
for (int i=10; i>=0; i--) {linkedHashMap.put(i, i);hashMap.put(i, i);}
System.out.println("LinkedHashMap (1): ");linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });
System.out.println("\nLinkedHashMap (2): ");
linkedHashMap.entrySet().forEach((e) -> {System.out.print(e.getKey() + " : " + e.getValue() + ", ");});

System.out.println("\n\nHashMap (1): ");hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });
System.out.println("\nHashMap (2): ");
hashMap.entrySet().forEach((e) -> {System.out.print(e.getKey() + " : " + e.getValue() + ", ");});}}

输出:

LinkedHashMap (1):10 (#=10):10, 9 (#=9):9, 8 (#=8):8, 7 (#=7):7, 6 (#=6):6, 5 (#=5):5, 4 (#=4):4, 3 (#=3):3, 2 (#=2):2, 1 (#=1):1, 0 (#=0):0,LinkedHashMap (2):10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1, 0 : 0,HashMap (1):0 (#:0):0, 1 (#:1):1, 2 (#:2):2, 3 (#:3):3, 4 (#:4):4, 5 (#:5):5, 6 (#:6):6, 7 (#:7):7, 8 (#:8):8, 9 (#:9):9, 10 (#:10):10,HashMap (2):0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10,
package com.test;
import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.Set;
public class Test {
public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("ram", "ayodhya");map.put("krishan", "mathura");map.put("shiv", "kailash");
System.out.println("********* Keys *********");Set<String> keys = map.keySet();for (String key : keys) {System.out.println(key);}
System.out.println("********* Values *********");Collection<String> values = map.values();for (String value : values) {System.out.println(value);}
System.out.println("***** Keys and Values (Using for each loop) *****");for (Map.Entry<String, String> entry : map.entrySet()) {System.out.println("Key: " + entry.getKey() + "\t Value: "+ entry.getValue());}
System.out.println("***** Keys and Values (Using while loop) *****");Iterator<Entry<String, String>> entries = map.entrySet().iterator();while (entries.hasNext()) {Map.Entry<String, String> entry = (Map.Entry<String, String>) entries.next();System.out.println("Key: " + entry.getKey() + "\t Value: "+ entry.getValue());}
System.out.println("** Keys and Values (Using java 8 using lambdas )***");map.forEach((k, v) -> System.out.println("Key: " + k + "\t value: " + v));}}

迭代地图非常容易。

for(Object key: map.keySet()){Object value= map.get(key);//Do your stuff}

例如,你有一个Map<String, int> data;

for(Object key: data.keySet()){int value= data.get(key);}

有很多方法可以做到这一点。下面是几个简单的步骤:

假设你有一个这样的Map:

Map<String, Integer> m = new HashMap<String, Integer>();

然后,您可以执行如下操作来迭代map元素。

// ********** Using an iterator ****************Iterator<Entry<String, Integer>> me = m.entrySet().iterator();while(me.hasNext()){Entry<String, Integer> pair = me.next();System.out.println(pair.getKey() + ":" + pair.getValue());}
// *********** Using foreach ************************for(Entry<String, Integer> me : m.entrySet()){System.out.println(me.getKey() + " : " + me.getValue());}
// *********** Using keySet *****************************for(String s : m.keySet()){System.out.println(s + " : " + m.get(s));}
// *********** Using keySet and iterator *****************Iterator<String> me = m.keySet().iterator();while(me.hasNext()){String key = me.next();System.out.println(key + " : " + m.get(key));}

使用Java8:

map.entrySet().forEach(entry -> System.out.println(entry.getValue()));

最紧凑的Java8:

map.entrySet().forEach(System.out::println);

使用Java8,您可以使用for每个和lambda表达式迭代Map,

map.forEach((k, v) -> System.out.println((k + ":" + v)));

在Map上有效的迭代解决方案是从Java5到Java7的for循环。

for (String key : phnMap.keySet()) {System.out.println("Key: " + key + " Value: " + phnMap.get(key));}

从Java8开始,您可以使用lambda表达式遍历Map。

phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));

如果你想为lambda写一个条件,你可以这样写:

phnMap.forEach((k,v)->{System.out.println("Key: " + k + " Value: " + v);if("abc".equals(k)){System.out.println("Hello abc");}});

我喜欢计算一个计数器,然后保存计数器的最终值;

int counter = 0;HashMap<String, String> m = new HashMap<String, String>();for(int i = 0;i<items.length;i++){m.put("firstname"+i, items.get(i).getFirstName());counter = i;}
m.put("recordCount",String.valueOf(counter));

如果你想恢复:

int recordCount = Integer.parseInf(m.get("recordCount"));for(int i =0 ;i<recordCount;i++){System.out.println("First Name :" + m.get("firstname"+i));}

使用Java7

Map<String,String> sampleMap = new HashMap<>();for (sampleMap.Entry<String,String> entry : sampleMap.entrySet()) {String key = entry.getKey();String value = entry.getValue();
/* your Code as per the Business Justification  */
}

使用Java8

Map<String,String> sampleMap = new HashMap<>();
sampleMap.forEach((k, v) -> System.out.println("Key is :  " + k + " Value is :  " + v));

如果我有一个在Java中实现Map接口的对象,并且我希望遍历其中包含的每一对,那么遍历map的最有效方法是什么?

如果循环密钥的效率是您的应用程序的优先事项,那么选择一个Map实现,以您想要的顺序维护密钥。

元素的排序是否取决于接口的特定map实现?

是的,绝对是。

  • 一些Map实现承诺一定的迭代顺序,而另一些则没有。
  • Map的不同实现维护不同的键值对顺序。

请参阅我创建的这个表格,其中总结了与Java11捆绑的各种Map实现。具体来说,请注意迭代顺序列。单击/点击以缩放。

Java11中的映射实现表,比较它们的特征

你可以看到四个#0实现维护订单

  • TreeMap
  • ConcurrentSkipListMap
  • LinkedHashMap
  • EnumMap

NavigableMap接口

其中两个实现了#0接口:TreeMapConcurrentSkipListMap

较旧的#0接口被较新的#1接口有效地取代。但是您可能会发现第三方实现仅实现旧接口。

自然秩序

如果您想要一个#0保持其对按键的“自然顺序”排列,请使用#1#2。术语“自然顺序”意味着键的类实现了#3#4方法返回的值用于排序中的比较。

定制订单

如果要为要用于维护排序顺序的密钥指定自定义排序例程,请传递适合密钥类的#0实现。使用#1#2,传递您的Comparator

原始插入顺序

如果您希望将地图对保持在您插入地图的原始顺序,请使用#0

枚举定义顺序

如果您使用#0#1之类的枚举作为键,请使用#2类。这个类高度不仅优化为使用很少的内存并且运行非常快,它还按照枚举定义的顺序维护您的对。例如,对于DayOfWeek,迭代时将首先找到DayOfWeek.MONDAY的键,DayOfWeek.SUNDAY的键将是最后一个。

其他考虑

在选择Map实现时,还要考虑:

  • NULL。一些实现禁止/接受NULL作为键和/或值。
  • 并发。如果您要跨线程操作映射,您必须使用支持并发的实现。或者用#0包装映射(不太可取)。

上面的图表涵盖了这两个考虑因素。

Map.forEach

简单地使用#0如何,其中键和值都传递给您的#1

map.forEach((k,v)->{System.out.println(k+"->"+v);});

从Java10开始,您可以使用局部变量推理(也称为“var”)来减少许多已经可用的答案的膨胀。例如:

for (var entry : map.entrySet()) {System.out.println(entry.getKey() + " : " + entry.getValue());}
Map<String, String> map =for (Map.Entry<String, String> entry : map.entrySet()) {MapKey = entry.getKey()MapValue = entry.getValue();}

您可以搜索键,并在键的帮助下找到映射的关联值,因为map有唯一密钥,看看当键重复这里这里时会发生什么。

演示地图:

 Map<String, String> map = new HashMap();map.put("name", "Name");map.put("age", "23");map.put("address", "NP");map.put("faculty", "BE");map.put("major", "CS");map.put("head", "MDK"); 

要仅获取密钥,您可以像这样使用map.keySet();

for(String key : map.keySet()) {System.out.println(key);}

要仅获取值,您可以像这样使用map.values();

      for(String value : map.values()) {System.out.println(value);}

要获取key及其值,您仍然可以使用map.keySet();并获取其对应的值,如下所示:

 //this prints the key value pairfor (String k : map.keySet()) {System.out.println(k + " " + map.get(k) + " ");}

map.get(key)给出该键指向的值。

这些都是迭代HashMap的可能方法。

HashMap<Integer,String> map=new HashMap<Integer,String>();map.put(1,"David");  //Adding elements in Mapmap.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());}    
}