深入理解集合框架层次结构(篇二)

本篇我们来谈映射(Map)

Map

映射数据结构是用来保存具有映射关系的数据,当要查看一个元素时,需要查找元素的精确副本。因此Map集合里存放着两组值key(键)和value(值)。其中key值唯一,不能重复,value值可重复。Java类库为映射提供了两个通用实现:HashMap(散列映射)和TreeMap(树映射),这两个类都实现了Map接口。

Map是无序的,(这里的有序和无序不是指集合中的排序,而是是否按照元素添加的顺序来存储对象。)它的存储结构是哈希表<key,value>键值对,map中插入元素是根据key计算出的哈希值来存储元素的,因此他不是按照元素的添加顺序来存储对象的,所以Map是无序的。它的实现类有:HashMap、TableMap和TreeMap。(LinkedHashMap是有序的)

应该选择散列映射还是树映射呢?

HashMap(散列映射):

HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。

  • HashMap基于哈希散列表实现,随机储存,无序。
  • 无论对于主键还是值都允许存为"null",只不过对于主键而言要求唯一性,所以key中最多存一个"null".
  • HashMap 线程不安全,同一时间允许多个线程同时进行操作,效率相对较高,但是可能会出现并发错误.

HashMap对外提供的常见访问接口:

  • put ()  ----HashMap对象可通过put()将映射关系数据(key--value)添加到HashMap中。
  • isEmpty()  ----判断是否为空
  • get()  ----获取key对应的value值
  • containsKey  ----判断HashMap是否包含key
  • containsvalue  ----判断HashMap是否包含value元素
  • putAll()  ----将具有多个映射关系数据的全部元素添加到HashMap中
  • remove()  ----删除键值为key的value值
  • clear()  ----清空HashMap,它是通过将所有的元素设为null来实现的。
  • enrtrySet()  ----返回“HashMap中所有Entry的集合”,它是一个集合。
  • keySet()  ----返回一个Set接口

HashMap遍历方式:

  • 遍历HashMap“键”集合:

keySet()  ----根据keySet()获取HashMap的“键”的Set集合,要想得到“value”,必须先得到key,再通过get(key)得到value(value依赖key)。

  • 遍历HashMap“值”集合:

values()  ----根据values()获取HashMap的“值”集合,再通过Iterator迭代器Next()得到值。

  • 遍历HashMap“键值对”集合:

entrySet()  ----根据entrySet()获取HashMap的“键值对”的Set集合,可通过get(key)和get(value)分别可直接得到两者的值(key和value不依赖)。

例:

package net.csdn.qf.homework;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
/**
 * @author 北冥有熊
 *  2018年11月5日
 */
public class Test01 {
	public static void main(String[] args) {
		HashMap<String, String> hm = new HashMap<String,String>();
		hm.put("00001", "张三");
		hm.put("00002", "李四");
		hm.put("00018", "王麻子");
		hm.put("00009", "赵武");
		System.out.println("=============="+hm); //无序输出
		
		//KeySet遍历
		Set<String> keySet = hm.keySet();//根据keySet()获取HashMap的“键”的Set集合。
		//通过Iterator迭代器开始遍历“第一步”得到的集合。
		Iterator<String> iterator = keySet.iterator();
		System.out.println("通过keySet遍历:");//
		while(iterator.hasNext()) {
			String key = iterator.next(); //得到键
			String value = hm.get(key); //通过键得到值
			System.out.println(key+":"+value);
		}
		
		//entrySet遍历
		Set<Entry<String, String>> entrySet = hm.entrySet();//根据entrySet()
								//获取HashMap的“键值对”的Set集合
		//通过Iterator迭代器开始遍历“第一步”得到的集合。
		Iterator<Entry<String, String>> iterator2 = entrySet.iterator();
		System.out.println("通过entrySet遍历:");
		while(iterator2.hasNext()) {
			Entry<String, String> entry = iterator2.next();//得到下一个
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key+":"+value);
			
		}
		//values遍历值
		Collection<String> c = hm.values();
		Iterator<String> iterator3 = c.iterator();
		System.out.println("通过values遍历:");
		while (iterator3.hasNext()) {
			String value = iterator3.next();
			System.out.println(value);
		}
	}
}

TreeMap(树映射):

TreeMap是一个键值唯一且有序的集合,底层实现基于“红黑树”。(红黑树:根节点是黑色,黑色的子节点必然是红色,从根节点到叶子节点含有的黑色数量是一致的。有关红黑树的实现原理参考https://www.cnblogs.com/CarpenterLee/p/5503882.html)。

HashMap 线程不安全,同一时间允许多个线程同时进行操作,效率相对较高,但是可能会出现并发错误.

由于TreeMap是有序的,故有特有方法时hashMap没有的。比如:

  • firstEntry()  ----返回一个与该图的最小密钥相关的键值映射,或 null如果Map是空的。
  • firstKey()  ----返回当前在该Map中的第一个(最低)键。

更多方法参见API

TreeMap遍历方式:

  • 遍历HashMap“键”集合:

keySet()  ----根据keySet()获取HashMap的“键”的Set集合,要想得到“value”,必须先得到key,再通过get(key)得到value(value依赖key)。

  • 遍历HashMap“值”集合:

values()  ----根据values()获取HashMap的“值”集合,再通过Iterator迭代器Next()得到值。

  • 遍历HashMap“键值对”集合:

entrySet()  ----根据entrySet()获取HashMap的“键值对”的Set集合,可通过get(key)和get(value)分别可直接得到两者的值(key和value不依赖)。

例:

package net.csdn.qf.test;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class Test06 {
	public static void main(String[] args) {
		TreeMap<String, Integer> aMap = new TreeMap<String,Integer>();
		aMap.put("AA", 18);
		aMap.put("BB", 9);
		aMap.put("CC", 100);
		System.out.println(aMap);
		
		//keySet遍历
		Set<String> keySet = aMap.keySet();
		Iterator<String> iterator = keySet.iterator();
		System.out.println("keySet遍历");
		while (iterator.hasNext()) {
			String key = iterator.next();
			Integer value = aMap.get(key);
			System.out.println(key+":"+value);
		}
		//entrySet遍历
		Set<Entry<String, Integer>> entrySet = aMap.entrySet();
		Iterator<Entry<String, Integer>> iterator2 = entrySet.iterator();
		System.out.println("entrySet遍历");
		while (iterator2.hasNext()) {
			Entry<String, Integer> nextEntry = iterator2.next();
			String key = nextEntry.getKey();
			Integer value = nextEntry.getValue();
			System.out.println(key+":"+value);
		}
		//value遍历
		Collection<Integer> values = aMap.values();
		Iterator<Integer> iterator3 = values.iterator();
		System.out.println("value遍历");
		while (iterator3.hasNext()) {
			Integer value = iterator3.next();
			System.out.println(value);
		}
	}
}

 

 

更多底层原理持续更新中。。。

 

 

猜你喜欢

转载自blog.csdn.net/qq_41892229/article/details/83897143