dictionary:如何有效地迭代Java Map中的每个条目?

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

元素的顺序是否依赖于接口的特定映射实现?


1
2
3
4
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() +"/" + entry.getValue());
}


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

使用iterator和Map.Entry

1
2
3
4
5
6
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();
}

使用foreach和Map.Entry

1
2
3
4
long i = 0;
for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
    i += pair.getKey() + pair.getValue();
}

使用Java 8中的forEach

1
2
final long[] i = {0};
map.forEach((k, v) -> i[0] += k + v);

使用keySet和foreach

1
2
3
4
long i = 0;
for (Integer key : map.keySet()) {
    i += key + map.get(key);
}

使用键集和迭代器

1
2
3
4
5
6
long i = 0;
Iterator<Integer> itr2 = map.keySet().iterator();
while (itr2.hasNext()) {
    Integer key = itr2.next();
    i += key + map.get(key);
}

使用for和Map.Entry

1
2
3
4
5
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();
}

使用Java 8流API

1
2
final long[] i = {0};
map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());

使用Java 8流API并行

1
2
final long[] i = {0};
map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());

使用Apache Collections的IterableMap

1
2
3
4
5
long i = 0;
MapIterator<Integer, Integer> it = iterableMap.mapIterator();
while (it.hasNext()) {
    i += it.next() + it.getValue();
}

使用Eclipse (CS)集合的MutableMap

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

性能测试(模式=平均时间,系统= windows 8.1 64位,Intel i7-4790 3.60 GHz, 16 GB)

对于小地图(100个元素),得分0.308是最好的

1
2
3
4
5
6
7
8
9
10
11
Benchmark                          Mode  Cnt  Score    Error  Units
test3_UsingForEachAndJava8         avgt  10   0.308 ±  0.021  μs/op
test10_UsingEclipseMap             avgt  10   0.309 ±  0.009  μs/op
test1_UsingWhileAndMapEntry        avgt  10   0.380 ±  0.014  μs/op
test6_UsingForAndIterator          avgt  10   0.387 ±  0.016  μs/op
test2_UsingForEachAndMapEntry      avgt  10   0.391 ±  0.023  μs/op
test7_UsingJava8StreamApi          avgt  10   0.510 ±  0.014  μs/op
test9_UsingApacheIterableMap       avgt  10   0.524 ±  0.008  μs/op
test4_UsingKeySetAndForEach        avgt  10   0.816 ±  0.026  μs/op
test5_UsingKeySetAndIterator       avgt  10   0.863 ±  0.025  μs/op
test8_UsingJava8StreamApiParallel  avgt  10   5.552 ±  0.185  μs/op

对于10000个元素的map,得分37.606是最好的

1
2
3
4
5
6
7
8
9
10
11
Benchmark                           Mode   Cnt  Score      Error   Units
test10_UsingEclipseMap              avgt   10    37.606 ±   0.790  μs/op
test3_UsingForEachAndJava8          avgt   10    50.368 ±   0.887  μs/op
test6_UsingForAndIterator           avgt   10    50.332 ±   0.507  μs/op
test2_UsingForEachAndMapEntry       avgt   10    51.406 ±   1.032  μs/op
test1_UsingWhileAndMapEntry         avgt   10    52.538 ±   2.431  μs/op
test7_UsingJava8StreamApi           avgt   10    54.464 ±   0.712  μs/op
test4_UsingKeySetAndForEach         avgt   10    79.016 ±  25.345  μs/op
test5_UsingKeySetAndIterator        avgt   10    91.105 ±  10.220  μs/op
test8_UsingJava8StreamApiParallel   avgt   10   112.511 ±   0.365  μs/op
test9_UsingApacheIterableMap        avgt   10   125.714 ±   1.935  μs/op

对于包含100000个元素的map,得分1184.767是最好的

1
2
3
4
5
6
7
8
9
10
11
Benchmark                          Mode   Cnt  Score        Error    Units
test1_UsingWhileAndMapEntry        avgt   10   1184.767 ±   332.968  μs/op
test10_UsingEclipseMap             avgt   10   1191.735 ±   304.273  μs/op
test2_UsingForEachAndMapEntry      avgt   10   1205.815 ±   366.043  μs/op
test6_UsingForAndIterator          avgt   10   1206.873 ±   367.272  μs/op
test8_UsingJava8StreamApiParallel  avgt   10   1485.895 ±   233.143  μs/op
test5_UsingKeySetAndIterator       avgt   10   1540.281 ±   357.497  μs/op
test4_UsingKeySetAndForEach        avgt   10   1593.342 ±   294.417  μs/op
test3_UsingForEachAndJava8         avgt   10   1666.296 ±   126.443  μs/op
test7_UsingJava8StreamApi          avgt   10   1706.676 ±   436.867  μs/op
test9_UsingApacheIterableMap       avgt   10   3289.866 ±  1445.564  μs/op

图(根据地图大小进行性能测试)

Enter image description here

表(性能测试取决于映射大小)

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

所有测试都在GitHub上。


在Java 8中,您可以使用新的lambdas特性快速而干净地完成它:

1
2
3
4
5
6
 Map<String,String> map = new HashMap<>();
 map.put("SomeKey","SomeValue");
 map.forEach( (k,v) -> [do something with key and value] );

 // such as
 map.forEach( (k,v) -> System.out.println("Key:" + k +": Value:" + v));

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

非常简单!


是的,顺序取决于特定的Map实现。

@ScArcher2具有更优雅的Java 1.5语法。在1.4中,我会这样做:

1
2
3
4
5
6
7
Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}


迭代映射的典型代码是:

1
2
3
4
5
6
Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap是规范映射实现,不做任何保证(如果没有对其执行任何更改操作,则不应该更改顺序)。SortedMap将根据键的自然顺序返回条目,如果提供,则返回一个ComparatorLinkedHashMap将根据其构造方式以插入顺序或访问顺序返回条目。EnumMap按键的自然顺序返回条目。

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


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

1
2
3
4
5
6
7
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();
  // ...
}


这是一个由两部分组成的问题:

如何迭代Map的条目- @ScArcher2完美地回答了这个问题。

迭代的顺序是什么——如果您只是使用Map,那么严格地说,没有顺序保证。因此,您不应该真正依赖于任何实现给出的顺序。然而,SortedMap接口扩展了Map,并提供了您正在寻找的内容——实现总是会给出一致的排序顺序。

NavigableMap是另一个有用的扩展——这是一个SortedMap与额外的方法寻找下令在关键位置设置条目。这可能可以删除首先需要迭代——你可以找到特定的entry你在使用higherEntry, lowerEntry, ceilingEntryfloorEntry的方法。descendingMap方法甚至为您提供了一种反转遍历顺序的显式方法。


有几种遍历map的方法。

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

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

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

50毫秒

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

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

76毫秒

3)使用entrySet()和迭代器

1
2
3
4
5
6
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()和迭代器

1
2
3
4
5
Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
    String key = itr2.next();
    testMap.get(key);
}

75毫秒

我已经提到this link


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

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


顺便说一下,如果您只对映射的键/值感兴趣,而对其他键/值不感兴趣,您还可以使用map.keySet()map.values()


对于Eclipse集合(以前是GS集合),您将在MapIterable接口上使用forEachKeyValue方法,该方法由MutableMap和ImmutableMap接口及其实现继承。

1
2
3
4
5
6
7
8
9
10
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);

使用Java 8 lambda语法,您可以编写如下代码:

1
2
3
4
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);

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


用Java 1.4试试:

1
2
3
4
5
6
7
8
for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

  Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() +"/" + entry.getValue());

  //...
}

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

在特殊的实现中,使用map.keySet()map.entrySet()或其他方法可能会有所不同。但我想不出为什么有人会这样写。很有可能,这对您所做的性能没有任何影响。

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

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


Java 8:

你可以使用lambda表达式:

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

要了解更多信息,请按此操作。


与Java 8

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

在Map中,你可以迭代keys和/或values和/或both (e.g., entrySet),这取决于你对…

1)。遍历地图的keys -> keySet():

1
2
3
4
5
Map<String, Object> map = ...;

for (String key : map.keySet()) {
    //your Business logic...
}

2)。遍历地图的values -> values():

1
2
3
for (Object value : map.values()) {
    //your Business logic...
}

3)。遍历地图的both -> entrySet():

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

此外,有三种不同的方法可以遍历HashMap。他们也一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//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);
}

Lambda Expression Java 8

在Java 1.8 (Java 8)中,通过使用来自聚合操作(流操作)的forEach方法,这变得容易得多,该方法看起来类似于来自Iterable接口的迭代器。

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

1
2
3
4
5
6
7
8
9
10
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表达式的示例代码。这东西太酷了。必须试一试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

同样也可以使用Spliterator。

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

更新

包括指向Oracle文档的文档链接。有关Lambda的更多信息,请访问此链接并必须读取聚合操作,而对于Spliterator,请访问此链接。


Java 8

我们有一个接受lambda表达式的forEach方法。我们也有流api。考虑一个地图:

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

遍历键:

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

遍历值:

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

迭代条目(使用forEach和Streams):

1
2
3
4
5
6
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()

forEachOrderedforEach的流?forEach不遵循遭遇战顺序(如果定义了),并且本质上是不确定性的,就像forEachOrdered所做的那样。所以forEach不能保证订单会被保留。还要查看更多信息。


如果你有一个通用的非类型化地图,你可以使用:

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();
        }
    }
}

最紧凑的Java 8:

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

1
2
3
4
5
6
    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());    
    }

你可以使用泛型:

1
2
3
4
5
6
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());
}

使用Java 8:

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
           //Functional Oprations
            Map<String, String> mapString = new HashMap<>();
            mapString.entrySet().stream().map((entry) -> {
                String mapKey = entry.getKey();
                return entry;
            }).forEach((entry) -> {
                String mapValue = entry.getValue();
            });

            //Intrator
            Map<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 loop
            Map<String, String> mapString = new HashMap<>();
            for (Map.Entry<String, String> entry : mapString.entrySet()) {
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();

            }

排序将始终依赖于特定的映射实现。使用java&c;8可以使用以下任何一种:

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

或者:

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

结果将是相同的(顺序相同)。由地图支持的入口集,所以你得到了相同的顺序。第二个很方便,因为它允许您使用lambdas,例如,如果您只想打印大于5的整数对象:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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("
LinkedHashMap (2):"
);

        linkedHashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() +" :" + e.getValue() +",");
        });


        System.out.println("

HashMap (1):"
);
        hashMap.forEach((k,v) -> { System.out.print(k +" (#:"+k.hashCode() +"):" + v +","); });

        System.out.println("
HashMap (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,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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));
    }
}

是的,正如许多人所同意的,这是遍历Map的最佳方法。

但是如果地图是null,则有可能抛出nullpointerexception。别忘了输入null .check in。

1
2
3
4
5
6
7
8
9
                                                 |
                                                 |
                                         - - - -
                                       |
                                       |
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
}


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

假设你有一张这样的地图:

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

然后,您可以执行如下操作来遍历映射元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ********** 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));
}

如果遍历Map的原因是对值执行操作并写入结果Map。我建议在谷歌Guava Maps类中使用transform-方法。

1
import com.google.common.collect.Maps;

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}

映射上有效的迭代解决方案是从Java 5到Java 7的"for each"循环。这里是:

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

从Java 8开始,您可以使用lambda表达式对映射进行迭代。它是一个增强的"forEach"

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

If you want to write a conditional for lambda you can write it like this:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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>() {
            @Override
            public void handler(K key, V value, Map<K, V> map) {
                System.out.println(key +" =" + value);
            }
        });
    }
}

例子

下面是一个例子。注意,Map的类型是由该方法推断的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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();
        }
    }
}

输出

1
2
3
4
5
6
7
One = 0
Two = 1
Three = 3

Object = java.lang.Object@15db9742
Integer = 0
Double = 0.0

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

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

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

KtypeVtype是伪代码。


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

1
2
3
4
5
6
7
8
9
10
11
12
/* 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();
}

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

使用iterator接口迭代映射时,必须使用条目或entrySet()

它是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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));
        }
    }
}

我用这个代码把一张地图的数据复制到另一张地图上:

1
2
3
4
5
6
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());
}

迭代映射非常简单。

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

例如,您有一个Map data;

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

快乐的编码…


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

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

1
2
3
4
5
6
7
8
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]));
}

输出:

1
2
69
1337