List集合:
有序 可重复的集合
有序:有元素的插入顺序
arrayList:
底层实现:数组
如何实现的:
创建数组的时候 长度是0
第一次添加元素的时候 初始化数组的长度 10
数组的扩容:
数组的元素个数超过10个的时候 扩容的工作
grow()
int newCapacity = oldCapacity + (oldCapacity >> 1);
=1.5*oldCapacity
数组扩容的时候 每次1.5倍进行扩容的
进行数组的复制的工作
数组的上限:arrayList数组的上限:Integer_max(21亿)-8
15亿------15*1.5=====22.亿
数组的上限 integer_maxvalue 21亿
arraylist的size的最大上限是integer_maxvalue
性能瓶颈10亿左右
右移1位 /2 2位 /4
左移:1 *2 2 *4
构造方法中有参构造 无参构造
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
有参构造的使用场景:
如果使用无参构造,初始化数组的长度0 第一次添加元素的时候开始 长度10 以后的每次扩容 1.5倍进行扩容
1000
10 15 22 33 50 75 112 。。。。
数组扩容----数组的拷贝的过程 消耗资源的过程
使用有参构造 参数:代表的是我们数组初始化的长度
参数500---750----1000+
当arraylist中元素个数很多的时候 最好使用有参构造 减少底层数组的扩容的次数 提升性能
add(E e)
remove(E e)
特点:
查询快 增删慢
数组有索引的 通过下标直接访问 时间复杂度o(1)
时间复杂度o(1) 数组 hash
LinkedList:
底层是一个链表结构的
链表:
线性链表:
单向:
只有一个方向的链表 上一个元素知道下一个元素 但是下一个元素不知道上一个元素的 访问的时候只能从一端开始
双向:
两个方向的链表 每一个元素 都知道自己的上一个元素和下一个元素是谁 可以从两个方向访问
环形链表:
收尾相连的链表
LinkedList的底层的结构 链表--线性的(1.5 单向的 1.5》》 双向的)
链表结构中的每一个元素 就叫做node 对象 Node
Node的结构:
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
addFirst(E e)
添加元素的时候 实际上是对Node的操作
优点:
增删快 查询慢
vector:
vector 和arrayList的区别
vector:线程安全的 但是性能低
arrayList 线程不安全的 性能高
stack:
栈结构
先进后出的
比较器:
内部比较器
comparable
.....ble 使。。。。。具备。。。。的能力
comparable 使。。。。具备比较的能力
如果一个类实现了这个接口 代表这个类具备了比较的能力
内部比较器 定义在对象类定义的时候 只能用于比较本类对象的
外部比较器
专门定义一个比较器的类 这个类中定义比较规则
comparator
定义在类的外部的 可以随着传入的泛型的类型 定义比较规则的
对list集合中的元素进行排序:
set集合:无序 不可重复的 无序:没有插入顺序的
set集合就是map集合的一部分 key
HashSet:Hashmap key
底层结构:
数组 16+链表(单向的)+树(红黑树)
元素存储的时候 先对元素取hash值
hash冲突 hash碰撞
hash算法:就是生成一个唯一的散列的数
不存在一个绝对完美的hash算法可以做到 任意两个甚至多个key的hash值不同的
任何一个hash算法都会存在hash冲突的问题
hash冲突:不同的key得到的hash值相同
Node<K,V>[] tab; 数组 数组的初始化容量 16
Node<K,V> p; 记录每一个元素的
int n, i; 记录数组的下标
数组扩容的节点:
数组进行扩容的阀值 数组的容量达到整个数组的0.75就会进行数组的扩容的操作 16*0.75=12
static final float DEFAULT_LOAD_FACTOR = 0.75f;
newCap = oldCap << 1 每次扩容 扩大2倍 32
hashset如何去重的:
hash值不同的两个元素 一定不是同一个元素
先判断hash值 equals方法(地址) 不存
TreeSet : treemap key
有序(元素值是排序的) 不可重复的
红黑树
排序:自然排序
数值:值的大小 默认升序的
字符串:字典顺序进行排序的
12 11 1 2 3 4 34 23 26
1
11
12
2
23
26
3
34
4
要求 我们的set集合中存放的元素是 有排序能力的
map:
treemap:
Hashmap:
hashTable 和hashMap:
hashtable 线程安全 性能低 整个数组的线程锁
hashmap 线程非安全的 性能高
concurrenthashMap: 既可以做到线程安全 又可以保证性能的
分段线程锁+读写锁
从数据的操作,锁的分类:
读锁:共享锁 所有的线程可以共用这把锁
写锁:排他锁 同一时间只能允许一个线程操作
会对hashMAP底层的数组进行分段加锁 通过具体的操作 决定加的是读锁还是写锁
排序算法:
回顾递归:
方法自己调用自己
递归原则:
1.必须写一个独立的方法
2.递归必须要有出口
死循环
3.递归 -- 有规律
用递归实现阶乘:
4!
4*3!
3*2!
2*1!
jc(int n){
出口:1!
if n==1:
return
n*jc(n-1);
}
不死神兔:
1 1 2 3 5 8 13 21
busishentu(){
出口:
}
10 8 9
6 7 7 8
4 5 5 6
快速:
找最终基准点的定位 定位 左侧 小 右侧 大
方法:
返回值:int index
参数:
array
计数排序:
归并