如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
当前回答
Lambda表达式Java 8
在Java1.8(Java8)中,通过使用Aggregate操作(Stream操作)中的forEach方法,这变得更加容易,它看起来类似于Iterable接口中的迭代器。
只需将下面的粘贴语句复制到代码中,并将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: 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。
Spliterator sit = hm.entrySet().spliterator();
更新
包括指向Oracle文档的文档链接。有关Lambda的更多信息,请访问此链接,必须阅读聚合操作,对于Spliterator,请访问该链接。
其他回答
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());
}
对于Eclipse集合,您将在MapIterable接口上使用forEachKeyValue方法,该方法由MutableMap和ImmutableMap接口及其实现继承。
MutableMap<Integer, String> map =
Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
MutableBag<String> result = Bags.mutable.empty();
map.forEachKeyValue((key, value) -> result.add(key + value));
MutableBag<String> expected = Bags.mutable.of("1One", "2Two", "3Three");
Assertions.assertEquals(expected, result);
将forEachKeyValue与EclipseCollections(EC)Map实现一起使用比使用entrySet更有效的原因是因为EC Map实现不存储Map.Entry对象。将entrySet与EC Map实现一起使用会动态生成Map.Entry对象。forEachKeyValue方法能够避免创建Map.Entry对象,因为它可以直接导航Map实现的内部结构。在这种情况下,使用内部迭代器比使用外部迭代器有好处。
注意:我是Eclipse集合的提交人。
//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 8,您可以使用以下任一选项:
map.forEach((k,v) -> { System.out.println(k + ":" + v); });
Or:
map.entrySet().forEach((e) -> {
System.out.println(e.getKey() + " : " + e.getValue());
});
结果相同(顺序相同)。entrySet由地图支持,因此您可以获得相同的顺序。第二个很方便,因为它允许您使用lambdas,例如,如果您只想打印大于5的Integer对象:
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,
有几种方法可以迭代地图。请参考以下代码。
使用迭代器接口迭代地图时,必须使用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));
}
}
}