Java集合框架概述(四)——Map体系集合与底层实现原理
2020-03-17 18:39
489 查看
一、Map父接口
1.概要
方法 | 描述 |
---|---|
public interface Map<K,V> | 将键映射到值的对象。 一个映射不能包含重复的键; 每个键可以映射到最多一个值。 |
将键映射到值的对象。 Map不能包含重复的键; 每个键可以映射到最多一个值。
Map界面提供了三个
collection视图 ,允许将映射内容视为键键、值集或键-值映射关系集。 映射的顺序定义在迭代器在映射的
collection示图上返回其元素的顺序。某些映射实现可明确保证其顺序,如
TreeMap类,另一些映射实现则不保证顺序,如
HashMap。
2.Map接口的特点:
- 用于存储任意键值对(Key-Value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
3.Map常见方法
方法 | 描述 |
---|---|
V put(K key, V value) | 将对象存入集合中,关联键值。key重复则覆盖原值 |
V get(Object key) | 如果此映射包含该键的映射,返回到指定键所映射的值,或 null。 |
Set keySet() | 返回此Map中所有的Key |
Collection values() | 返回包含所有值的Collection集合 |
Set<Map.Entry<K,V>> entrySet() | 键值匹配的Set集合 |
4.应用场景
在进行字典查询时,通过List接口的下标查询已经不能满足要求,因为用户不能根据元素下标轻松查询到对应位置的值,两者在直观性并不强。
public class CountryMap { public static void main(String[] args){ System.out.println("请输入国家的缩写:"); Scanner scanner = new Scanner(System.in); String s = Country.countries.get(scanner.nextLine()); System.out.println("查询结果为:"+s); } } class Country{ public static final Map<String,String> countries = new HashMap<>(); static { countries.put("CN","中华人民共和国"); countries.put("US","美利坚合众国"); countries.put("KR","韩国"); countries.put("JP","日本"); } }
打印结果:
5.keySet()
方法和Values()
方法
在要点3中罗列出了
keySet()方法和
Values()方法,两者分别表示返回所有键、返回所有值,但是前者接收的方式是
Set集合,后者则是
Collection结合。原因在于:
Key是唯一的,
Value是不唯一且无序的
public class CountryMap { public static void main(String[] args){ //所有键(Key是唯一的,因此时Set接收) Set<String> keys = Country.countries.keySet(); System.out.println(keys); //所有值(值是无序的,且是不唯一的) Collection<String> values = Country.countries.values(); System.out.println(values); } } class Country{ public static final Map<String,String> countries = new HashMap<>(); static { countries.put("CN","中华人民共和国"); countries.put("US","美利坚合众国"); countries.put("KR","韩国"); countries.put("JP","日本"); } }
打印结果:
二、Map的实现类
1.HashMap
基于哈希表的实现的Map接口。 此实现提供了所有可选的映射操作,并允许null的值和null键。( 除了它是不同步的,并允许null之外,
HashMap类大致相当于
Hashtable)。这个类不能保证映射的顺序; 特别是,它不能保证该顺序恒久不变。
- JDK1.2版本,线程不安全,运行效率快;允许使用
null
作为Key
或者是value
。
HashSet是对HashMap的实现:
用户所有存进
HashSet中的值,
HashSet会原封不动的提交给
HashMap的Key,进而根据Key来进行排序
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { private transient HashMap<E,Object> map; } public boolean add(E e) { return map.put(e, PRESENT)==null; }
2.Hashtable
该类实现了一个哈希表,它将键映射到值。 任何非null对象都可以用作键值或值。
为了从散列表成功存储和检索对象,用作键的对象必须实现hashCode方法和equals方法。
- JDK1.0版本,线程安全,运行效率慢;不允许使用
null
作为Key
或者是value
。
3.TreeMap
该方法可以讲Map中的键值对按照键值的进行自然排序;同样的,根据HashMap和HashSet的关系,事实上TreeSet是基于TreeMap的实现,即用户所有存进
TreeSet中的值,
TreeSet会原封不动的提交给
TreeMap的Key,进而根据Key来进行排序。
//伪代码 class TreeSet<E>{ private TreeMap<E,?> map; public void add(E,e){ map.put(e,null); } } calss TreeMap<K k ,V v>{ public void put(K k, V v){ } }
三、Map的真面目——数组链表
前面我们使用了
keySet()方法和
Values()方法来分别返回Map的所有键和所有值,那怎样但返回所有 键-值对呢?显然,会使用到
Set<Map.Entry<K,V>> entrySet()方法。
该方法的返回类型是Set,但是与
Values()方法不同的是,Set的泛型一个
Map.Entry<K,V>也是一个泛型,这里就涉及到了Map的底层实现原理了
JDK1.8中,用户所有存入Map的键值都会存入
Node<K,V>[]类型的
table数组,而
Node<K,V>实现了
Map.Entry<K,V>,实质上Map本身是一个数组。(JDK1.7中使用的不是
Node<K,V>[]而是
Entry<K,V>)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
默认的数组的长度为16,且每个元素都有对应的类型就是
Entry<K,V>,当用户在new一份新的HashMap对象时,会把
HashMap<K,V>对应的值传给
Entry<K,V>
/** *该表在首次使用时初始化,并调整为 *必填。分配后,长度始终是2的幂。 *(我们在某些操作中也允许长度为零,以允许 *当前不需要的引导机制。) */ transient Node<K,V>[] table; /** *保存缓存的entrySet()。请注意,使用AbstractMap字段 *用于keySet()和values() */ transient Set<Map.Entry<K,V>> entrySet;
//公开的静态内部类 static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } }
横向看Map数组状,存储了16个主要元素,接着每一个元素下有挂靠了以链表结构存储的其他元素。
现因个人能力有限,具体详细分析可参考博文:
Java中HashMap底层实现原理(JDK1.8)源码分析
- 应用:
public class CountryMap { public static void main(String[] args){ //所有键和值 Set<Map.Entry<String,String>> entries = Country.countries.entrySet(); for (Map.Entry<String,String> entry: entries){ System.out.println(entry); } } } class Country{ public static final Map<String,String> countries = new HashMap<>(); static { countries.put("CN","中华人民共和国"); countries.put("US","美利坚合众国"); countries.put("KR","韩国"); countries.put("JP","日本"); } }
打印结果:
- 点赞 1
- 收藏
- 分享
- 文章举报
相关文章推荐
- List、Map、Set集合底层数据结构及实现原理
- List、Map、Set集合底层数据结构及实现原理
- 深入理解Array、List、Map集合框架底层实现原理
- java集合各实现类的底层实现原理
- (11) java集合 ---- LinkedHashMap和HashMap等Map的比较使用以及 LinkedHashMap的实现原理
- 深入源码看数据结构--集合和Map底层实现
- List、set、Map的底层实现原理
- java集合的底层实现原理
- Java集合系列之ArrayList底层实现原理
- 集合各实现类的底层实现原理
- 史上最详尽 Java 8 集合类 HashMap : 底层实现和原理学习笔记(源码解析)
- 黑马程序员【Java集合框架(下)Map实现原理】
- Java集合系列之HashSet的底层实现原理
- [重磅,建议收藏]JAVA集合框架中的常用集合及其特点、适用场景、实现原理简介
- Spring AOP概述及底层实现原理
- [重磅,建议收藏]JAVA集合框架中的常用集合及其特点、适用场景、实现原理简介
- JAVA集合框架中的常用集合及其特点、适用场景、实现原理简介
- 集合各实现类的底层实现原理
- Java Map-集合实现原理
- List、set、Map的底层实现原理