目录

set集合

HashSet

元素新增

TreeSet

红黑树

Map

HashMap

ConcurrentHashMap

TreeMap

LinkedHashMap

set集合

 set集合主要看一下两个:HashSet、TreeSet

HashSet

特点是:

特点:无序,不重复
扩容: 初始容量16,负载因子0.75,扩容增量1倍

示例:new HashSet<>(20, 0.5f);

它存储唯一元素并允许空值
依据对象的hashcode来确定该元素是否存在
由HashMap支持
不保持插入顺序
非线程安全

HashSet底层就是用HashMap实现的,也就是非线程安全.

 private transient HashMap<E,Object> map;//构造一个初始容量16,加载因子是0.75的HashMap
public HashSet() {map = new HashMap<>();
}

既然是用HashMap实现的,那么问题来了,Set存的只是一个对象,而HashMap存的是<K,V>键值对,怎么用HashMap作为Set的底层呢?

元素新增

private static final Object PRESENT = new Object();
public boolean add(E e) {return map.put(e, PRESENT)==null;
}

可以看到,HashSet只使用了HashMap的key,而值PRESENT是一个对象常量。这也是为什么Set里面的元素都是唯一的。

返回是map.put(e, PRESENT)==null表达式,HashMap在新增值的时候如果已有则返回旧值,反之,返回null,所以这也是Set判断重复添加值的时候是否添加成功。

TreeSet

特点:是一个包含有序的且没有重复元素的集合
作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序,可以在对象出重写比较器,也要重写hashCode方法可以根据自己需求来比较排序,也可以在方法内新建对象来new一个比较器,在对象里面需要重写hashCodee方法

public class Student implements Comparable<Student>{private Integer sid;private String sname;private int age;public Student(Integer sid, String sname, int age) {super();this.sid = sid;this.sname = sname;this.age = age;}public Integer getSid() {return sid;}public void setSid(Integer sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((sid == null) ? 0 : sid.hashCode());result = prime * result + ((sname == null) ? 0 : sname.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Student other = (Student) obj;if (age != other.age)return false;if (sid == null) {if (other.sid != null)return false;} else if (!sid.equals(other.sid))return false;if (sname == null) {if (other.sname != null)return false;} else if (!sname.equals(other.sname))return false;return true;}@Overridepublic String toString() {return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";}@Overridepublic int compareTo(Student o) {if(this.getAge()-o.getAge()==0) {return this.getSid()-o.getSid();}return this.getAge() - o.getAge();}

TreeSet的底层是TreeMap,而TreeMap底层数据结构是红黑树。

public TreeSet() {this(new TreeMap<E,Object>());}

TreeMap的节点结构如下:

class Entry<K,V> implements Map.Entry<K,V> {K key;V value;Entry<K,V> left;Entry<K,V> right;Entry<K,V> parent;boolean color = BLACK;}

红黑树的起源,自然是二叉查找树了,这种树结构从根节点开始,左子节点小于它,右子节点大于它。每个节点都符合这个特性,所以易于查找,是一种很好的数据结构

红黑树

注:红黑数是平衡二叉树的一种,插入时遵循二叉树“左右”定律:

该父节点的左子节点:小于父节点中且子树中最接近父节点值得数。

该父节点的右子节点:大于父节点中且子树中最接近父节点值得数。

Map

特点:

无序,键值对,键不能重复,值可以重复,
键重复则覆盖,没有继承Collection接口

遍历方式:

先获取所有键的Set集合,再遍历(通过键获取值)
取出保存所有Entry的Set,再遍历此Set即可

扩容:初始容量16,负载因子0.75,扩容增量1倍

常用类型

HashMap  ConcurrentHashMap   TreeMap  LinkedHashMap

HashMap

线程不安全,最常用,速度快
    内部采用数组来存放数据

基本原理

put执行过程

Table数组中的的Node的数据结构

在jdk 1.8之前是这样的一个链表式结构,根据传出的key值来进行哈希值计算,确认放到那个桶内

,如果桶内有重复的值则覆盖掉,没有则把原来的元素往下挤

在jdk 1.8的时候则是改成红黑树结构

流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。

根据传出的key值来进行哈希值计算,确认放到那个桶内,如果桶内有重复的值则覆盖掉,则根据根节点来判断值的大小,来分配

ConcurrentHashMap

线程安全,性能高用的比较多,还有一个HashTable这个类方法则是加了一把锁给锁锁住了,运行进程会慢。

源码:读写时会进行上锁,每一个桶也就是每一个节点会上一把锁分段锁,默认16把锁

 final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();int hash = spread(key.hashCode());int binCount = 0;for (Node<K,V>[] tab = table;;) {Node<K,V> f; int n, i, fh; K fk; V fv;if (tab == null || (n = tab.length) == 0)tab = initTable();else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))break;                   // no lock when adding to empty bin}else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else if (onlyIfAbsent // check first node without acquiring lock&& fh == hash&& ((fk = f.key) == key || (fk != null && key.equals(fk)))&& (fv = f.val) != null)return fv;else {V oldVal = null;synchronized (f) {if (tabAt(tab, i) == f) {if (fh >= 0) {binCount = 1;for (Node<K,V> e = f;; ++binCount) {K ek;if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;if (!onlyIfAbsent)e.val = value;break;}Node<K,V> pred = e;if ((e = e.next) == null) {pred.next = new Node<K,V>(hash, key, value);break;}}}else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,value)) != null) {oldVal = p.val;if (!onlyIfAbsent)p.val = value;}}else if (f instanceof ReservationNode)throw new IllegalStateException("Recursive update");}}if (binCount != 0) {if (binCount >= TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;}

TreeMap

  • key值按一定的顺序排序,基于红黑树,容量无限制,非线程安全,比较常用
  • 添加或获取元素时性能较HashMap慢(因为需求维护内部的红黑树,用于保证key值的顺序)
  • 能比较元素的大小,根据key比较(元素的自然顺序,集合中自定义的比较器也可排序)
private TreeMap<String,Student> treeMap;@Beforepublic void setup() {treeMap = new TreeMap<String,Student>(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {// 负数   0  正数return o1.compareTo(o2);}});treeMap.put("1", new Student(5, "小白"));treeMap.put("2", new Student(3, "小黑"));treeMap.put("3", new Student(2, "小黄"));treeMap.put("4", new Student(4, "小明"));treeMap.put("3", new Student(1, "小黑"));treeMap.put("4", new Student(4, "小明"));}

LinkedHashMap

继承HashMap
维护了一个双向链表
LinkedHashMap是有序的,且默认为插入顺序
默认情况下使用entryset获取的集合顺序是与节点的插入顺序(默认是按照插入的顺序进行排列的,最先插入的节点(即最老的节点)为head,最新插入的节点为tail)

注意:有序和无序是描述系统内部状态、客观事物内部各要素以及客观事物之间关系的范畴。有序指系统的组成元素、事物内部诸要素或事物之间的有规则的排列、组合、运动和转化,含结构有序与运动有序;无序则相反,指事物内部诸要素或事物之间、系统内部组成元素之间混乱而无规则的组合、运动和转化,含结构无序和运动无序。有序和无序是世界上存在的两种情形,二者的差异是相对的,世间没有绝对的有序和无序,在有序的事物中存在着破坏其有规则的排列或运动过程的因素,无序的事物中总是包含有有序的因素

J2EE从入门到入土02.Set及Map集合解析相关推荐

  1. J2EE从入门到入土04.Map集合

    回顾:J2EE从入门到入土03.Set集合 目录 Map接口 Map实现类介绍 HashMap 遍历实例 输出结果 基本原理 HashTable ConcurrentHashMap TreeMap L ...

  2. 【MyBatis从入门到入土】6 - 关联、集合

    11 关联.集合 在MySQL中,我们经常需要处理一对多的情况,使用MyBatis中的高级映射就能够很好地处理这种情况. 11.1 数据库中创建测试表 创建学生表student和教师表teacher, ...

  3. Flink 教程 gitbook 从入门到入土(详细教程)

    Flink从入门到入土(详细教程) 和其他所有的计算框架一样,flink也有一些基础的开发步骤以及基础,核心的API,从开发步骤的角度来讲,主要分为四大部分 1.Environment Flink J ...

  4. rocketmq怎么保证消息一致性_从入门到入土(三)RocketMQ 怎么保证的消息不丢失?...

    精彩推荐 一百期Java面试题汇总SpringBoot内容聚合IntelliJ IDEA内容聚合Mybatis内容聚合 接上一篇:RocketMQ入门到入土(二)事务消息&顺序消息 面试官常常 ...

  5. Activiti工作流从入门到入土:完整Hello World大比拼(Activiti工作流 API结合实例讲解)

    文章源码托管:https://github.com/OUYANGSIHAI/Activiti-learninig 欢迎 star !!! 本来想着闲来无事,前面在项目中刚刚用到了工作流 Activit ...

  6. activiti api文档_【白银人机】Activiti 工作流从入门到入土:完整 hello world 大比拼(API 结合实例讲解)...

    点击上方"好好学java",选择"置顶"公众号 重磅资源.干货,第一时间送达 重磅推荐  ① 纯福利 | 公众号资源大汇总,一年才一次! ② 重磅!!2018年 ...

  7. Java入门篇 2021/02/22

    Java入门篇 2021/02/22 Java的三大版本 java三大版本主要包括 JavaSE, JavaME, JavaEE,其中现如今的JavaME已经是很少见了,JavaSE是JavaEE的基 ...

  8. 从入门到入土(十)RocketMQ集群流程以及核心概念

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:从入门到入土(九)手摸手教你搭建RocketMQ双主双从同步集群 ...

  9. 从入门到入土(九)手摸手教你搭建RocketMQ双主双从同步集群,不信学不会!...

    精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 Mybatis内容聚合 接上一篇:从入门到入土(八)RocketMQ的Consumer是如何做的负 ...

最新文章

  1. CF525D Arthur and Walls
  2. 通信行业还是一个靠人际的行业
  3. 我使用的博客和通讯工具汇总
  4. java 浏览器 安全设置_IE浏览器安全设置脚本
  5. php与JAVA的RSA加密互通
  6. 软件测试之黑盒测试-边界值分析法(理论白话学习/期中期末备考)
  7. (递推1)兔子繁殖问题
  8. 记:使用IScroll.js 开发picker日历组件遇到的问题及经验总结
  9. pr调色预设_视频调色不好掌握?用这2000套PR、AE、达芬奇调色预设吧
  10. 数据分析没价值?——深思对业务的洞察有多少?
  11. 【线段树】 SPOJ 2713 Can you answer these queries IV
  12. Thingsboard 3.1.0 - 数据订阅
  13. 实现DEDE转跳属性文档在模板上调用出转跳地址
  14. Spring之AOP的实现
  15. layout 工程师如何提升自己? 2020-3-27
  16. springboot springsecurity接入cas单点登录,前后端分离
  17. JavaScript的事件委托(事件代理)原理
  18. linux安装nginx1.21.1全教程(含安装包)
  19. 根据UI设计图得到android所需要的dp
  20. SNP位点上下游序列查找1.0 2020-9-27

热门文章

  1. 修改element-ui tree树结构前的图标,及树形结构的样式
  2. 树莓派+ros_arduino_bridge 运行报错 “[Errno 13] Permission denied“
  3. 想成长的设计师必须知道的事情!(深度好文)
  4. 《计算机网络》中英文对照
  5. f420 虚拟服务器,F420双线实现上海电信IPTVAB认证
  6. FL Studio的入门教程——通道机架
  7. 每一趟安心出行的背后,都有哪些黑科技?
  8. 香港市场人民币IPO为何吸引眼球?
  9. GreenDao教程(3):一对一,一对多,多对多
  10. Html 表单提交 【js获取表单提交数据】