集合
存储数据的一种容器、内置了大量的方法,可以进行数据的CRUD。
泛型
JDK5中 , Java语言新增了 对泛型的支持。泛型主要应用于集合。
Java 中 泛型 在定义类的时候,默认采用 擦拭法。
在使用集合的时候,传入的是什么具体类型,那么在定义泛型类的时候,泛型指的就是传入的类型。
在使用泛型的时候,可以 传入 任何数据类型(除8种基本数据类型),泛型不支持基本数据类型。
在 定义带有泛型的类中,使用泛型的时候,泛型类型(不确定的类型) 不能使用 new 创建对象, 但可以使用 Class 类对象构建对象
在 类上 使用 泛型
在定义一个类的时候,可以在类的后面使用
<>
来定义泛型, 在<>
传入1 ~ N个大写字母, 多个泛型用逗号分割~
类上 声明的泛型 和 对象有关 、和 成员属性、成员方法、构造方法有关系 ~
一个类中 静态方法中使用的泛型 和 类上定义的泛型 没有任何关系,所以静态方法需要在返回值的前面使用<>
来声明泛型
泛型 通配符
PECS法则
extends : 可以限定传入的数据类型的上限, 只能生产数据、而不能消费数据 !
super :可以限定传入的数据类型的下限,可以消费数据、生产的数据都是Object !
集合的分类
集合的主要作用 就是 存储数据的,数据是存储在内存中的 ~
-
Collection(单值集合)
- List (单值、存储的数据有序、元素可以重复)
- ArrayList (底层采用数组结构进行存储、是一个线性表、根据索引查询时间复杂度O(1), 增删O(n))
- LinkedList (底层采用链表结构进行存储、是一个链表、根据索引查询时间复杂度O(n), 增删O(1))
- CopyOnWriteArrayList : 在高并发环境下使用的的 List, 可以保证线程安全!
- Vector : 线程安全、底层和 ArrayList 一样
- Stack : 是一个栈结构的类型、
- Set (单值、存储的数据无序、采用hash算法。元素不可重复)
- HashSet : 采用 Hash算法,将数据 分散在 散列 表
- TreeSet : 对存入的数据会进行排序
- CopyOnWriteArraySet : 在高并发环境下使用的的 Set, 可以保证线程安全!
- List (单值、存储的数据有序、元素可以重复)
-
Map (键值对集合)
- HashMap : 采用 hash 算法存储数据,键无序且不可重复 , HashSet 是通过 HashMap 实现的
- TreeMap : 对存入的键 进行排序
- ConCurrentHashMap : 在高并发环境下使用的的 Map, 可以保证线程安全!
- Hashtable : 是线程安全的、且 键和值 均不能为 null
- Properties : 是 Hashtable的子类、可以存储操作系统的环境变量 和 操作 Java语言的properties配置文件
ArrayList 底层实现原理
- 底层采用 一个数组 存储数据
- 默认初始因子是 10
- 每次扩容 1.5倍、当扩容的长度达到 Integer.MAX_VALUE - 8 的时候,再次扩容,每次扩容的长度为 1, 当超出了Integer的最大值的时候,会抛出 OutOfMemoryError异常
LinkedList 链式结构
-> 双链表
List 静态方法
- of(E…) : 快速 构建一个 只读集合 。
- copyOf(Collection) : 将一个已存在的可读写的集合 构建成一个 只读集合。
HashSet 去重的原理
首先会根据 值的 hash值 进行查找元素、如果 hash 值相同,且 equals 比较的内容 也相同, 则 添加失败 ~~
TreeSet
能够对传入的对象进行 自然排序, 如果 想要实现自然排序、那么 传入的对象所有的类 需要实现 Comparable接口
或者 在构建 TreeSet的时候,通过构造方法传入一个 Comparator , 当两个对象在比较的时候 如果相等,则会自动去重~
Set 静态方法
- of(…) 快速构建一个只读的 Set集合
- copyOf(Collection)
Collections 工具类
是 Collection 集合的 工具类
-
max(collection) : 获取集合中的最大元素、元素必须实现 Comparable接口
-
min(collection) :
-
max(collection, comparator) : 获取元素的最大值、可以传入比较器
-
min(collection, comparator)
-
reverse(list) : 反转 list 列表
-
sort(list, comparator) : 对 list 集合进行排序
-
shuffle(list) : 随机打乱
Map
是用来表示 键值对 结构的容器, 一个键对应一个值。
HashMap 遍历方式
- keySet() : 键遍历
- values() : 值遍历(不常用、根据值无法获取键)
- entrySet() : 键值对遍历
- forEach(consumer) : 底层采用的是键值对遍历, 无法控制循环~
练习:
编写一个方法,用来统计 字符串中每一个字符出现的次数
HashMap 底层实现
JDK8 : 数组 + 链表 + 红黑二叉树
JDK<8 : 数组 + 链表
- HashMap 初始因子 16
- HashMap 的加权因子 0.75
- HashMap 每次扩容 2倍
- HashMap 通过( n - 1) & hash 定位元素
HashMap 为什么初始因子是 16,且每次扩容 2倍
HashMap的初始因子 只要是 2个 幂次方即可、扩容2倍 是因为 通过 (n - 1) & hash 该公式
计算得到的索引 在 扩容 2倍的时候,得到的结果 是 原来的位置 或者是 原位置 + 扩容长度
当 进行扩容的时候, 原来的数据 进行 重新分配位置的时候,减少 hash 冲突 。
什么是 Hash碰撞 或者 Hash冲突
对键进行计算的时候,得到的值 相同,那么 根据 公式 (n-1)&hash 得到的索引也会相同,从而导致
在 定位数组中元素的时候,产生 数据冲突 。
怎么解决 Hash 冲突
- Java 中 hashMap 采用的 链表 或者 二叉树 (链地址法)
- 再哈希法。
TreeMap
ConCurrentHashMap / Hashtable
键和值均不允许为 null
Properties
键和值 均为 字符串的 Map , 他的父亲是 Hashtable , 所以 Properties 键和值 均不能为 null。
- 读取 系统的环境变量
Properties p = System.getProperties();
// 根据键获取值
p.getProperty(key);
p.setProperty(key, val);
- 读取 java 的 properties 配置文件
Java 语言比较常用的配置文件 有 .properties , .xml , .yml(yaml)