概述
Map.Entry是Map接口的一个内部接口,用于获取Map元素的键值对。可以通过map.entrySet()的返回值是一个Set,其类型为Map.Entry,常用的有以下几个方法:
- getKey():获取元素的键
- getValue():获取元素的值
- setValue():设置元素的值
实例
Map类型数据的遍历方式
package com.linfanchen.springboot.lab.map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MapEntryTest {
@Test
public void carPriceTest() {
Map<String, Integer> carPriceMap = new HashMap<>();
carPriceMap.put("bmw", 500000);
carPriceMap.put("benz", 550000);
carPriceMap.put("lexus", 440000);
// 遍历方式一:使用Map.keySet()
for (String key : carPriceMap.keySet()) {
System.out.println("key=" + key + ", value=" + carPriceMap.get(key));
}
// 遍历方式二(推荐):使用Map.entrySet()的iterator()迭代器
Iterator<Map.Entry<String, Integer>> iterator = carPriceMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
}
// 遍历方式三(推荐):entrySet()
for (Map.Entry<String, Integer> entry : carPriceMap.entrySet()) {
System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
}
// 遍历方式四:使用map.values()只能获取值
for (Integer val : carPriceMap.values()) {
System.out.println("value=" + val);
}
}
}
遍历效率
代码
写个Case验证一下:
package com.linfanchen.springboot.lab.map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MapEntryTest {
@Test
public void carPriceTest() {
Map<String, Integer> carPriceMap = new HashMap<>();
carPriceMap.put("bmw", 500000);
carPriceMap.put("benz", 550000);
carPriceMap.put("lexus", 440000);
// 遍历方式一:使用Map.keySet()
for (String key : carPriceMap.keySet()) {
System.out.println("key=" + key + ", value=" + carPriceMap.get(key));
}
// 遍历方式二(推荐):使用Map.entrySet()的iterator()迭代器
Iterator<Map.Entry<String, Integer>> iterator = carPriceMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
}
// 遍历方式三(推荐):entrySet()
for (Map.Entry<String, Integer> entry : carPriceMap.entrySet()) {
System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
}
// 遍历方式四:使用map.values()只能获取值
for (Integer val : carPriceMap.values()) {
System.out.println("value=" + val);
}
}
@Test
public void speedTest() {
{
// 构造500w的数据源
HashMap<Integer, String> hashmap = new HashMap<Integer, String>();
for (int i = 0; i < 5000000; i++) {
hashmap.put(i, "lfc");
}
long bs = Calendar.getInstance().getTimeInMillis();
Iterator iterator = hashmap.keySet().iterator();
while (iterator.hasNext()) {
hashmap.get(iterator.next());
}
System.out.print("keyset:");
System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
}
{
// 构造500w的数据源
HashMap<Integer,String> hashmap = new HashMap<Integer,String>();
for (int i = 0; i < 5000000; i++ ) {
hashmap.put(i, "lfc");
}
long bs = Calendar.getInstance().getTimeInMillis();
Iterator it = hashmap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
entry.getValue();
}
System.out.print("entryset:");
System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
}
}
}
输出:
keyset:120
entryset:98
从输出结果看出entryset的方式便利性能会好很多,那为什么呢?
从源码找答案:
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
- hashmap.entryset:在set集合中存放的是entry对象。而在hashmap中的key 和 value 是存放在entry对象里面的;然后用迭代器,遍历set集合,就可以拿到每一个entry对象;得到entry对象就可以直接从entry拿到value了;
- hashmap.keyset:只是把hashmap中key放到一个set集合中去,还是通过迭代器去遍历,然后再通过 hashmap.get(key)方法拿到value;
源码
位于 java.util.Map
:
public interface Entry<K, V> {
/*
* 获取键
*/
K getKey();
/*
* 获取值
*/
V getValue();
/*
* 设置值
*/
V setValue(V var1);
boolean equals(Object var1);
int hashCode();
/*
* 根据键比较,具体比较的逻辑
*/
static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
return (Comparator)((Serializable)((c1, c2) -> {
return ((Comparable)c1.getKey()).compareTo(c2.getKey());
}));
}
/*
* 根据值比较,具体比较的逻辑
*/
static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
return (Comparator)((Serializable)((c1, c2) -> {
return ((Comparable)c1.getValue()).compareTo(c2.getValue());
}));
}
/*
* 根据键比较,具体比较的逻辑
*/
static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator)((Serializable)((c1, c2) -> {
return cmp.compare(c1.getKey(), c2.getKey());
}));
}
/*
* 根据值比较,具体比较的逻辑
*/
static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator)((Serializable)((c1, c2) -> {
return cmp.compare(c1.getValue(), c2.getValue());
}));
}
}
总结
在日常的开发中,要注意map类型的遍历效率。可以使用entrySet()高效遍历,节省程序的运行时间。PS:苹果系统为什么能那么流畅,就是尽量优化每一行代码的效率,我们也要遵循一样的理念。