JAVA day20、21 双列集合Map<K,V>:HashMap,LinkedHashMap,TreeMap,Hashtable, ConcurrentHashMap;JDK1.9新特性
一、Map<K,V>
类型参数:
K
- 此映射所维护的键的类型
V
- 映射值的类型
所有已知子接口:
Bindings, ConcurrentMap<K,V>, ConcurrentNavigableMap<K,V>, LogicalMessageContext, MessageContext, NavigableMap<K,V>, SOAPMessageContext, SortedMap<K,V>
所有已知实现类:
AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap
1.特点
1).Map集合是一个双列集合,是以key-value的形式表示。
2).key和value都可以使用泛型,也就意味着可以使用引用数据类型(自定义类)
3).key值都不允许有重复值。
4).value值允许有多个重复值。
5).如果key值出现一致的情况,则value值会被覆盖。
6).因为key是唯一的,可以通过key找到value值。
与Collection的区别:
2.实现类
1.HashMap<K,V>
HashMap 的实例有两个参数影响其性能:初始容量 (16)和加载因子(0.75)。
容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。
加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。
当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
a.默认初始容量:16
b.加载因子: 0.75 -> 容量达到百分之75的时候进行扩容
b.如果元素太少就进行扩容,会造成空间的浪费
c.如果元素太多进行扩容,则会造成效率低下
常用API
import java.util.HashMap;//HashMap 是Map集合接口的实现类 他的常用API
public class HashMapDemo01 {public static void main(String[] args) {HashMap<String,String> hm = new HashMap<>();//添加集合元素hm.put("肖战","王一博");hm.put("小松菜奈","管田将晖");hm.put("Pepper Potts","Tony Stark");hm.put(null,"yeah");//键为空hm.put("hi",null);//值为空//hashmap里允许键或者值为空的情况System.out.println(hm);//{null=yeah, hi=null, Pepper Potts=Tony Stark, 小松菜奈=管田将晖, 肖战=王一博}//输出排序是按hashcode值排序/* boolean containsKey(Object key)如果此映射包含对于指定键的映射关系,则返回 true。*/Object b = hm.containsKey("肖战");System.out.println(b);//trueObject b1 = hm.containsKey("小白");System.out.println(b1);//false/* boolean containsValue(Object value)如果此映射将一个或多个键映射到指定值,则返回 true。 */Object b2 = hm.containsValue("管田将晖") ;System.out.println(b2);//true/* boolean isEmpty()如果此映射 不包含 键-值映射关系,则返回 true。 */Object b3 = hm.isEmpty();System.out.println(b3);//false/* V remove(Object key)从此映射中移除指定键的映射关系(如果存在)。 */Object v1 = hm.remove("小松菜奈");System.out.println(v1);//管田将晖System.out.println(hm);//{null=yeah, hi=null, Pepper Potts=Tony Stark, 肖战=王一博}Object v2 = hm.remove("灰原哀");//不存在的key值System.out.println(v2);//null/*int size()返回此映射中的键-值映射关系数。 */System.out.println(hm.size());//4}
}
Map集合的遍历
1.键找值⽅式:即通过元素中的键,获取键所对应的值
2.Entry键值对对象
3.键值对⽅式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
import java.util.*;/*Map 集合的遍历Set<Map.Entry<K,V>> entrySet()返回此映射所包含的映射关系的 Set 视图。Set<K> keySet()返回此映射中所包含的键的 Set 视图。Collection<V> values()返回此映射所包含的值的 Collection 视图。*/
public class HashMapDemo02 {public static void main(String[] args) {Map<Integer,String> map = new HashMap<>();map.put(1,"小白");map.put(2,"小红");map.put(3,"小黑");map.put(4,"小黄");System.out.println(map);//{1=小白, 2=小红, 3=小黑, 4=小黄}/*Set<Map.Entry<K,V>> entrySet()返回此映射所包含的映射关系的 Set 视图。*/Set<Map .Entry<Integer,String>> set = map.entrySet();for (Map .Entry<Integer,String> m :set) {System.out.println(m);//获取键Integer key = m.getKey();//获取值String value = m.getValue();System.out.println(key + "="+ value);}/*Set<K> keySet()返回此映射中所包含的键的 Set 视图。*/Set<Integer> set1 = map.keySet();//创建迭代器Iterator<Integer> it = set1.iterator();while(it.hasNext()){//获取keyInteger key1 = it.next();String value1 = map.get(key1);//通过键获取值System.out.println(key1+"="+value1);}/** Collection<V> values()返回此映射所包含的值的 Collection 视图。*/Collection<String> col = map.values();for (String s:col) {String value2 = s;System.out.println(value2);}}
}
LinkedHashMap:
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。(如果在调用 m.put(k, v) 前 m.containsKey(k) 返回了 true,则调用时会将键 k 重新插入到映射 m 中。)
底层数据结构:数组+链表+双向链表
import java.util.LinkedHashMap;//HashMap的子类LinkedHashMap
public class LinkedHashMap01 {public static void main(String[] args) {LinkedHashMap<Integer,String> linked = new LinkedHashMap<>();linked.put(44,"开心");linked.put(5,"不开心");linked.put(777,"哈哈哈哈");System.out.println(linked);//{44=开心, 5=不开心, 777=哈哈哈哈}//这里输出就会按照程序插入顺序排列,与HashMap不一样}}
2.TreeMap<K,V>
基于红黑树(Red-Black tree)的 NavigableMap
实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator
进行排序,具体取决于使用的构造方法。
注意,如果要正确实现 Map 接口,则有序映射所保持的顺序(无论是否明确提供了比较器)都必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 Comparable 或 Comparator)。这是因为 Map 接口是按照 equals 操作定义的,但有序映射使用它的 compareTo(或 compare)方法对所有键进行比较,因此从有序映射的观点来看,此方法认为相等的两个键就是相等的。即使排序与 equals 不一致,有序映射的行为仍然是 定义良好的,只不过没有遵守 Map 接口的常规协定。
3.Hashtable<K,V>
此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null
对象都可以用作键或值。
为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode
方法和 equals
方法。
与HashMap对比:
转至: https://blog.csdn.net/strivenoend/article/details/80396893
两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。
HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key。
HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口。
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1。
HashMap和Hashtable的底层实现都是数组+链表结构实现。
两者计算hash的方法不同:
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模key和value是否允许null值
Hashtable中,key和value都不允许出现null值。但是如果在Hashtable中有类似put(null,null)的操作,编译同样可以通过,因为key和value都是Object类型,但运行时会抛出NullPointerException异常,这是JDK的规范规定的。
HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。两个遍历方式的内部实现上不同
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
hash值不同
哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。
Hashtable计算hash值,直接用key的hashCode(),而HashMap重新计算了key的hash值,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。
内部实现使用的数组初始化和扩容方式不同
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。 Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。
4.ConcurrentHashMap<K,V>
支持获取的完全并发和更新的所期望可调整并发的哈希表。此类遵守与 Hashtable
相同的功能规范,并且包括对应于 Hashtable 的每个方法的方法版本。不过,尽管所有操作都是线程安全的,但获取操作不 必锁定,并且不 支持以某种防止所有访问的方式锁定整个表。此类可以通过程序完全与 Hashtable 进行互操作,这取决于其线程安全,而与其同步细节无关。
底层数据结构:
JDK1.7: 数组 + 链表
Segment数组 + hashEntry数组 + hashEntry链表
JDK1.8: 数组 + 链表|红黑树
CAS + synchronized(同步锁)
与HashMap对比:
https://blog.csdn.net/xuefeng0707/article/details/40834595
二、JDK1.9新特性:of( )
3. of()只能适用于List/Set/Map集合,不指定到实现类中
4.of()的返回值是一个不可改变的集合,否则都会抛出UnsupportedOperationException - 不支持的异常
5.Set/Map集合在调用of()的时候,不能有重复值,否则就会抛出IllegalArgumentException - 非法参数异常
import java.util.ArrayList;
import java.util.List;/*
* JDK1.9 新特性 of() 静态方法 接口名调用
* 插入值,就不用一个一个添加了
*
* */
public class Demo01 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();//原始添加方法list.add(4);list.add(5);list.add(88);list.add(9);System.out.println(list);//[4, 5, 88, 9]List<Integer> list1 =List.of(2,8,5,6666,89,25);System.out.println(list1);//[2, 8, 5, 6666, 89, 25]//能获取集合里面的值System.out.println(list1.get(0));//2//不能增加元素//list1.add(555);//UnsupportedOperationException//不能更改里面的元素//list1.set(1,99);//UnsupportedOperationException//不能删除元素//list1.remove(2);//UnsupportedOperationExceptionSystem.out.println(list1);}
}
JAVA day20、21 双列集合Map<K,V>:HashMap,LinkedHashMap,TreeMap,Hashtable, ConcurrentHashMap;JDK1.9新特性相关推荐
- 【Java】如何理解Java中的双列集合Map?
1 Map<K,V>接口 1.1 特点 双列集合一个元素包含俩值 Key不可以重复,Value可以重复 Key和Value一一对应 Key和Value可以时任意类型 1.2 常用方法 pu ...
- java 双列集合Map 万字详解
目录 一.前言 二.概述 三.特点 四.常用方法 1. V put(K key, V value) : Δ代码演示 : 2. V get(Object key) : Δ代码演示 : 3. V remo ...
- java 中遍历双列集合_获取单列集合,双列集合,数组的Stream流对象以及简单操作...
获取流对象 获取单列集合,双列集合,数组的流对象 单列集合获取流对象: 1.java.util.Collection接口中加入了default方法stream()获取流对象,因此其所有实现类均可通过此 ...
- 双列集合Map的实现类
Map接口[和Collection接口并列] Map接口 成员方法[实现于Map接口,TreeMap也可实现,这里以HashMap为例] //HashMap实现类 :无序[HashSet底存原理] 哈 ...
- Java双列集合之Map以及斗地主案列
Map集合 知识点-- 概述 讲解 图文演示 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射.Java提供了专门的 ...
- java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part9~整起(单双列集合们、ArrayList 的扩容机制、HashMap、ConcurrentHashMap )
再进入正文之前,先看看集合相关操作的时间复杂度: 本故事源自于~ 开唠: PART0: 为什么突然蹦出集合这个玩意,就是因为咱们基础那里学的"数组"不够用~: 数组一般用来保存一组 ...
- Map双列集合的用法,遍历方法
Map集合的常用方法. Map集合是一个双列集合,里面的每个元素都是一个键值对. Map<K,V> 有两个泛型, K 表示Map集合中键的类型. V 表示Map集合中值的数据类型. 常用方 ...
- Java中的Map集合及其子类HashMap,LinkedHashMap,TreeMap,ConcurrentHashMap
一 .Map public interface Map<K,V> 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.此接口哦取代了Dictionary类,后者完全是 ...
- Java---Map双列集合
目录 一.双列集合的介绍 二.Map的使用 1:Map中常见的API (1)put方法 (2)remove方法 2:Map的遍历 (1)通过键找值的方式遍历 (2)通过键值对对象遍历 (3)Lambd ...
最新文章
- Java 15 转正了,国内几大互联网公司均有贡献,其中腾讯最为突出!
- ML 01、机器学习概论
- 转:Jeff Dean的Stanford演讲
- boost::endian模块实现benchmark的测试程序
- defer和async属性详解
- java模拟火车站买票的过程_Java常用代理
- 项目开发日志:Build AssetBundle——SpriteAtlas(已解惑)
- try catch php 捕获,php try catch : 捕捉异常,抛出异常
- python协成_Python协程技术的演进
- [实验流体力学][Matlab] pi 定理的应用
- 内核线程和用户线程(SMP)
- 什么叫做形态学图像处理_形态学腐蚀和膨胀原理和python实现
- 操盘手 李彪 照片[转]
- 【“科大讯飞杯”第十七届同济大学】A 张老师和菜哭武的游戏
- 有一个Map集合里面存储的是学生的姓名和年龄,内容如下{赵四=21,王二=17,张三=18,小丫=25,李四=26,王五=38}(15分) 	 * a.将里面的元素用两种遍历方式打印到控制台上 	 *
- java 截取图片后缀
- 面经手册 · 第1篇《认知自己的技术栈盲区》
- 从专升本到互联网大厂-我的2021
- FFmpeg简单使用:视频编码 ---- YUV转H264
- Linux应用开发: SQLite数据库交叉编译部署与运用
热门文章
- 地热热泵系统行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- echarts-X轴不从0刻度开始 代码实现
- Web工程师必备的可视化工具
- vue2.0的Element UI的表格table列时间戳格式化
- Go 应用优化“指北”
- 这就是程序员被大厂偏爱的实力!
- 堪称神器的命令行工具系列——curl
- 打破“打工人”魔咒,RPA 来狙击!
- 不要再被Python洗脑了,来看看这个吧......
- 疫情下的国内云市场,正是大展拳脚的好时机!