Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

8.6. Map

		
Map
 ├Hashtable
 ├HashMap
 └WeakHashMap
 
 Map接口
  请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
Hashtable类
  Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
  添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:
    Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));
  要取出一个数,比如2,用相应的key:
    Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);
  由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方 法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相 同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如 果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希 表的操作。
  如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
  Hashtable是同步的。
HashMap类
  HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。
WeakHashMap类
  WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
		
		

8.6.1. 初始化

		
	Map<String, Object> data = new HashMap<String, Object>() {
		{
			put("name", "neo");
		}
	};		
		
			

8.6.1.1. static map

			
	private static final Map<String, String> point;
	static {
		point = new HashMap<String, String>();
		point.put("CN", "China");
		point.put("HK", "Hongkong");
		point.put("TW", "Taiwan");
	};
			
				
			
	public final static Map<String, String> hostMap = new HashMap<String, String>() {
        {
            put("redis", "127.0.0.1");
            put("solr", "127.0.0.1");
        }
	};
		
		
	public final static Map map = new HashMap() {{      
	    put("key1", "value1");      
	    put("key2", "value2");      
	}};  		
			
				

8.6.1.2. Collections 初始化 Map

				
Map<String, String> emptyMap = Collections.emptyMap();
				
public static Map<String, String> createSingletonMap() {
    return Collections.singletonMap("username1", "password1");
}
				
				
				

8.6.1.3. 使用 Collectors.toMap()初始化 Map

数组方式

				
Map<String, String> map = Stream.of(new String[][] {
  { "Hello", "World" }, 
  { "Neo", "Chen" }, 
}).collect(Collectors.toMap(data -> data[0], data -> data[1]));
				
				
				

对象方式

				
 Map<String, Integer> map = Stream.of(new Object[][] { 
     { "Neo", 1 }, 
     { "Netkiller", 2 }, 
 }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));				
				
				

使用 Collectors.collectingAndThen()初始化不可变的Map

				
Map<String, String> map = Stream.of(new String[][] { 
    { "Hello", "World" }, 
    { "John", "Doe" },
}).collect(Collectors.collectingAndThen(
    Collectors.toMap(data -> data[0], data -> data[1]), 
    Collections::<String, String> unmodifiableMap));
				
				

8.6.1.4. 使用Map.Entry流初始化 Map

使用 Entry 接口的SimpleEntry 实现 :

				
Map<String, Integer> map = Stream.of(
  new AbstractMap.SimpleEntry<>("idea", 1), 
  new AbstractMap.SimpleEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

				
				

使用SimpleImmutableEntry 实现:

				
Map<String, Integer> map = Stream.of(
  new AbstractMap.SimpleImmutableEntry<>("idea", 1),    
  new AbstractMap.SimpleImmutableEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

				
				

8.6.1.5. Map.of()

				
Map<String, String> emptyMap = Map.of();
Map<String, String> singletonMap = Map.of("key1", "value");
Map<String, String> map = Map.of("key1","value1", "key2", "value2");				
				
				

8.6.1.6. Map.ofEntries()

				
Map<String, String> map = Map.ofEntries(
  new AbstractMap.SimpleEntry<String, String>("name", "Neo"),
  new AbstractMap.SimpleEntry<String, String>("city", "Shenzhen"),
  new AbstractMap.SimpleEntry<String, String>("zip", "518000"),
  new AbstractMap.SimpleEntry<String, String>("home", "https://www.netkiller.cn")
);				
				
				

8.6.2. HashMap

8.6.2.1. 遍历 HashMap

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

session.put("A",1);
...
...
session.put("Z",26)

for (Map.Entry<String, Integer> entry : session.entrySet()) {
	System.out.println(String.format("%s:%d", entry.getKey(), entry.getValue()));
}

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

			
				

8.6.2.2. 遍历map中的键

			
Map<Integer, Integer> map = new HashMap<Integer, Integer>();  
  
//遍历map中的键  
  
for (Integer key : map.keySet()) {  
  
    System.out.println("Key = " + key);  
  
}  			
			
				

8.6.2.3. 遍历map中的值 

			
Map<Integer, Integer> map = new HashMap<Integer, Integer>();    
for (Integer value : map.values()) {  
    System.out.println("Value = " + value);  
}  			
			
				

8.6.2.4. 通过键取值

			
Map<Integer, Integer> map = new HashMap<Integer, Integer>();  
  
for (Integer key : map.keySet()) {  
  
    Integer value = map.get(key);  
  
    System.out.println("Key = " + key + ", Value = " + value);  
  
}  			
			
				

8.6.2.5. 使用 Iterator 遍历 HashMap

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

Map map = new HashMap();  
  
Iterator entries = map.entrySet().iterator();
  
while (entries.hasNext()) {  
  
    Map.Entry entry = (Map.Entry) entries.next();  
  
    Integer key = (Integer)entry.getKey();  
  
    Integer value = (Integer)entry.getValue();  
  
    System.out.println("Key = " + key + ", Value = " + value);  
}  
			
				

8.6.3. LinkedHashMap

		
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class TestLinkedHashMap {
 
  public static void main(String args[])
  {
   System.out.println("*** LinkedHashMap ***");
   Map<Integer,String> map = new LinkedHashMap<Integer,String>();
   map.put(6, "apple");
   map.put(3, "banana");
   map.put(2,"pear");
   
   for (Iterator it =  map.keySet().iterator();it.hasNext();)
   {
    Object key = it.next();
    System.out.println( key+"="+ map.get(key));
   }
   
   System.out.println("*** HashMap ***");
   Map<Integer,String> map1 = new  HashMap<Integer,String>();
   map1.put(6, "apple");
   map1.put(3, "banana");
   map1.put(2,"pear");
   
   for (Iterator it =  map1.keySet().iterator();it.hasNext();)
   {
    Object key = it.next();
    System.out.println( key+"="+ map1.get(key));
   }
  }
}
		
			

8.6.4. 遍历数据

			
        Map<Integer, String> map = new HashMap<Integer, String>(){{
            put(1, "127.0.0.1");
            put(2, "192.168.0.1");
            put(3, "172.16.0.1");
        }};
        for (Integer key : map.keySet()) {
            System.out.println("key= "+ key + ", value= " + map.get(key));
        }			
			
			

8.6.5. 迭代器

			
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }			
			
			

8.6.6. Map forEach

		
Map<String, Integer> items = new HashMap<>();
items.put("A", 10);
items.put("B", 20);
items.put("C", 30);
items.put("D", 40);
items.put("E", 50);
items.put("F", 60);

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

//output
key : A value : 10
key : B value : 20
key : C value : 30
key : D value : 40
key : E value : 50
key : F value : 60

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

8.6.7. 随机取值

			
        Map<Integer, String> map = new HashMap<Integer, String>(){{
            put(1, "127.0.0.1");
            put(2, "192.168.0.1");
            put(3, "172.16.0.1");
        }};

        Integer[] keys = map.keySet().toArray(new Integer[0]);
        Random random = new Random();
        Integer randomKey = keys[random.nextInt(keys.length)];
        String randomValue = map.get(randomKey);

        System.out.println(randomValue);