4.20 复习回顾
集合 collection
1.集合的使用
ArrayList a = new ArrayList();
2.集合中的API
通用api
添加: a.add()
删除:a.remove()
判断集合是否为空:a.isEmpty()
交集:a.retainAll(a1)
并集:a.addAll(a1)
元素数量:a.size()
将集合转为数组:a.toArray();
查询:contains()
3.collection 子接口
3.1list
list接口 通用特点
list 具有有序不唯一的特点
有序:添加顺序排序
不唯一:可以存在相同的元素
因为具有顺序 所以新增了操作下标的API
添加到指定位置 :add(index i);
获取指定位置的元素 : ger(index i);
遍历方式
同时 也拥有了 四种遍历方式
增强 for 普通for 迭代器iterator 还有 专属list的ListIterator
list的三种常用实现类
list里边又下分了几个实现类
分别是: ArrayList、Vectore、LinkedList
ArristList 和 Vector 的相同与不同
先把Arraylist和vector放在一起说
特点 :查询快 增删慢
相同点:
1.Arraylist 和 Vector 底层都是用数据进行存储的
不同 vector 是线程安全的 但效率低
ArrayList 线程不安全 效率高
扩容 规则:
ArrayList 底层数组默认长度是 0
第一次创建对象时 给数组扩容 变为10 之后每次 扩容都是 之前的1.5倍
Vector 底层数组默认长度是10
方式一: capacityIncrement<=0 新的容量 oldCapacity*2
方式一: capacityIncrement>0 新的容量 oldCapacity+capacityIncrement;
list的另一个子类 LinkedList
LinkedList
底层是链表 存储数据 特点 :查询慢 但是增删快
相较于 List 又新增了操作头尾的方法
给 头 尾 添加值 :addFirst() addLast()
获取头尾的值 : getFirst() getLast()
删除头尾 : removeFirst() removeLast()
3.2 set
set是 collection 的另一个 子接口
同样 set也拥有三个 常用实现子类 : HashSet LinkedHashSet TreeSet
set 相较于 collection 没新增的 方法 同样也只有 两种遍历方式 : 增强for 和 迭代器 iterator
set的 实现类 (三种实现类底层其实都是map)
HashSet :底层是 哈希表存储
特点 : 无序(元素排列没有顺序)
唯一 :相同元素只能存在 一个
给 集合添加 自定义类型时:必须重写 equals 和 hashCode 方法
LinkedHashSet : 底层是 哈西表+链表
有序 (元素按添加顺序排列)
唯一 : 相同元素只能存在 一个
给 集合添加 自定义类型时:必须重写 equals 和 hashCode 方法
TreeSet : 底层是 红黑树
特点 : 有序 (比较顺序)
唯一 :相同元素只能存在 一个
给 集合添加 自定义类型时: 自定义类型 继承 comparable接口 制定比较规则
或者 创建比较类 comparator 制定比较规则
集合 map
colleaction 传入的一个数值 map 传入的是一个 键值对
使用方式
与collection 大致相同 存在 一个 key 和 value
特点 :喜新厌旧——— 如果key相同 新的value会替换旧的value
三个实现类
HashMap:
key: 无序:不是添加顺序 在哈西表内的存储顺序
唯一: 如果key 相同 新的value 会替换旧的value 喜新厌旧
value:满足泛型要求即可
底层: 哈西表
注意:如果key是自定义类型 那么需要重写 equals hashCode()
LinkedHashMap:
key:
有序:添加顺序
唯一:如果key 相同 新的value 会替换旧的value 喜新厌旧
value:满足泛型要求即可
底层: 哈西表+链表
注意:如果key是自定义类型 那么需要重写 equals hashCode()
TreeMap:
key:
有序:排序顺序
唯一:如果key 相同 新的value 会替换旧的value 喜新厌旧
value:满足泛型要求即可
底层:红黑树
注意:如果key是自定义类型 那么需要指定比较规则
TreeMap判断重复的标准 是比较规则返回 0
map的 底层源码
map的存储原理
一.创建对象后、实例初始化 ---》 普通成员变量 显示赋值语句 构造器内容
底层顺序表类型
transient Node<K,V>[] table;
第一次创建对象时没有给底层数组开辟空间 只是给负载因子 赋值为 0.75f
this.loadFactor = DEFAULT_LOAD_FACTOR;
二.进行数据存储
2.0 第一次添加数据
给底层数组开辟长度为16的数组
threshold:12
2.1 第一次添加 key 为null
存到下标为0的位置
2.2 非第一次添加 指定位置没有值
直接添加
2.3 非第一次添加 指定位置有值 hash相同 key 也相同
新的value替换旧的vlaue 并将旧的value 返回 喜新厌旧
2.4 非第一次添加 指定位置有值 hash相同 key不同
追加到原有节点的下面
七上八下
jdk7: 在原有节点的上面添加
jdk8:追加到原有节点的下面
2.5 扩容 和树化
扩容: size > threshold 会扩容 数组长度和阈值扩大到原来的2倍
树化:
1. 某个位置节点的数量>=8
2. 数组长度>=64
HashMap 与 HashTable
相同 : 都是 map接口的实现类
底层都是使用 哈希表进行存储
不同 : HashTable 线程是安全的 但是效率低 HashMap 线程不安全 效率高
key 和value 都不能是null key和 value 都可以是null
创建对象 给数组开辟空间 为 11 不给数组开辟空间
泛型
理解:
好比瓶子 厂家出厂瓶子 我们不知道这个瓶子是用来装什么的 ,因此我们需要给瓶子贴上一个标签 ------这个标签就是泛型
也可以 参考形参来理解
什么地方 可以用到泛型 ?
类:
接口:
方法:
类:
ArrayList<E>
HashSet<E>
HashMap<K,V>
接口:
List<E>
Collection<E>
interface Comparator<T>
方法: 调用方法时才能确定类型的方法
Collections.addAll(list,"张三","李四");
自定义泛型
自定义泛型类
class A<T>{}
泛型接口
interface<T>B{}
泛型方法: 返回值前进行泛型的声明
[修饰符] <T> 返回值类型 方法名(){
}
泛型的上限与擦除
指定泛型的上限:
T extends 类型
T:所能接收的数据类型是 类型以及类型的孩子
<T extends Number>
T:所能接收的数据类型是 Number以及类型的Number
T extends 类型 & 接口
T extends Number & Comparable
T:所能接收的数据类型 既是Number以及类型的孩子也是 Comparable接口的孩子
泛型的擦除:
1.如果是一个泛型资源却没有指定泛型 那么使用最高类型 Object
2.泛型只存在于编译时