Java 集合整理笔记

整理笔记:
在说集合之前要先了解数据结构

数据结构

数据结构:存放数据的方式
数组 链表 栈 队列 二叉树

1、顺序结构
1.底层实现:数组

在这里插入图片描述
在这里插入图片描述

2.特点:

1)按照顺序排序,并且每个元素都带有标号
2)除了标号是连续的,内存中的物理空间也是连续的

3.功能:

增加 - 存储数据 add()
删除 - 删除数据 remove()
修改 - 修改数据 set()
查看 - 获得数据 get()

4.优缺点:

优点:因为有下标,所以查询速度快
缺点:插入/删除效率低。对空间使用率相对较低,因为需要连续的物理内存空间

2、链式结构
1.底层数据结构:

链表

2.底层实现:

Node(节点) -> (data(数据) + next(下一个节点的引用))

3.特点:

a.链表的物理内存空间不是连续的,应用率高
b.操作的是Node(data + next)
c.所有操作都必须从头节点开始,并且头节点不存数据

4.几种不同的链表:
a.单向链表

特点:Node-next,只能从头开始往下找在这里插入图片描述

b.双向链表

特点:Node-next,可以从头开始往下找,也可以从尾往前找
head:不存数据,没有next
foot:不存数据,没有pre

c.循环链表

特点: Node-next,尾节点(有data数据的节点)指向头节点,可以在任意位置开始,都可以获取到想要的元素
在这里插入图片描述

总结: 顺序结构和链式结构统称为:线性结构(代表有固定顺序的结构)

集合:

1、Iterable接口:
1.API只有一个

itertor - 迭代器

2.作用:遍历/迭代数组(集合)

前提:必须继承Iterable接口。必须可迭代的。

3.iterator - 迭代器
a.运行原理:

获得迭代器,是有游标的,并且游标在第一个元素之前

b.三个方法:

hasNext() - 询问有没有下一个元素

next() - 获取下一个元素

remove() - 删除元素
注意: remove()不能使用集合中的remove(),因为会发生异常,只能使用迭代器自身的remove()

ConcurrentModificationException

c.简易版迭代器 - foreach

结构:
for(对象:集合){
要输出的内容;
}
:前 -> 每一次迭代出来的临时变量
:后 -> 要迭代的集合/数组

2、泛型:

泛型可以直接替换所有存放类型的地方(方法参数/返回值/类/接口)

运行时状态 -> 在JVM底层中支持的类型是Object。只是编译时状态添加,用来规范程序员写法的

Collection col = new Collection<>();

3、分类:

Collection - 接口(包含有很多子接口/实现类)

创建: Collection col = new ArrayList() ——> 向上造型

		Collection:
			|- List - 线性结构
				| - ArrayList(C) - 顺序结构 - 数组
				| - LinkedList(C) - 链式结构 - 双向链表
				| - Vector(C) - 顺序结构 - 数组
					| - Stack - 栈
			|- Set - 散列结构(没有顺序)
				| - HashSet(C) - 散列结构
				| - SortSet(I) - 
					| - TreeSet(C) - 二叉树
			|- Queue - 队列
				| - Deque(I) - 双端队列,栈(根据方法区分)
					| - LinkedList(C) - 链式结构 - 双向链表
		Map - 接口(包含很多子接口/实现类)
			| - HashMap(C) - 散列结构
				| - LinkedListHashMap(C) - 线性结构
			| - HashTable(C) - 散列结构 
			| - ConcurrentHashMap(C) - 散列结构
			| - SortedMap(I)
				| - TreeMap(C) - 二叉树
4、Collection子接口:在这里插入图片描述
1、List集合 - 线性结构

1)特点:
a.List集合是有顺序的,所以是有序列表,可以使用游标
b.List集合允许有重复的值
2)独有方法:
get(int index)

set(int index, E element)

remove(int index)

add(int index, E element)

addAll(int index, Collection<? extends E> c)

indexOf(Object o)

lastIndexOf(Object o)

subList(int fromIndex, int toIndex) - 截取子集合
截取特点: 前包含,后不包含
3)常用实现类:

ArrayList

顺序结构 - 数组

LinkedList

链式结构

(1)特点:

a. LinkedList是双向链表
b. 双向链表有头节点和尾结点,可以从头节点开始,头节点不存数据(data) 只有next。可以从尾节点开始,尾节点不存数据(data) 只有pre
c. 所有的操作都必须从头节点或者尾节点出发
d. LinkedList 也是 Deque的实现类

(2)独有方法:

特点: First/Last
addFirst() - 从头加入元素
addLat() - 从尾加入元素
getFirst() - 获得集合中的第一个元素
getLast() - 获得集合中的最后一个元素
removeFirst() - 删除集合中的第一个元素
removeLast() - 删除集合中的最后一个元素

Vector

顺序结构 - 数组

1、特点:

a.Vector上带有线程同步锁(synchronized)
所以都是线程安全的,效率相对较低

2、Set集合:

1. HashSet©:散列表(没有顺序,不是随机!!!)
特点:
a.存储位置不是真正的随机,内存存储位置根据hashCode值计算 - 无序的
b.不允许有重复值 - 使用equals方法判断是否重复
存储过程:

①根据hashCode计算内存位置
②如果位置上没有元素,就直接添加
③如果位置上有元素,则使用equals方法进行比较
④比较时,如果相同则不存入
⑤如果不相同,挨个遍历链表中的元素,使用equals比较是否相同,如果不相同则在链表末尾添加

结论:
hashCode 和 equals 必须一起重写
2. SortedSet(I) - 父接口 - 可排序的集合
TreeSet©:

(1)底层数据结构:二叉树

(2)特点:
TreeSet是可排序的集合,并且专门用于Set集合的排序

(3)存储过程:

①跟根节点进行比较 - compareTo方法进行比较
② 如果比根节点大,存储在右边
③ 如果比根节点小,存储在左边
④ 如果和根节点一样,就不存入

3、Queue集合 - 队列

底层实现:基于数组或者链表实现

1)特点:

a.先进先出
b.队列也是线性结构,是有顺序的,但是没有标号
2)常用API:

offer() - 添加
peek() - 单独获取,队列不变
poll() - 获取并移除,队列改变

3)子接口 - Deque(I)

1)Deque作为队列实现 - 双端队列
有First/Last的方法
特有方法:

offerFirst()
offerLast()
peekFirst()
peekLast()
pollFirst()
pollLast()

2)Deque作为栈实现

a.特点:先进后出(后进先出)

b.特有方法:
push() - 进栈
pop() - 出栈

区分栈或者是双端队列:

因为最终的实现类都是LinkedList,所以只能通过方法区分

4、排序:

1.自然排序(默认排序) 和 自定义比较器排序

1)自然排序:

a.自定义的类要实现自然排序,就要再类中实现Comparable接口
b.并且重写Comparable接口中的 compareTo()
c.如果是JDK提供的类,就必须实现Comparable接口

2)自定义比较器:

a.使用匿名内部类形式直接实现Comparetor接口
b.并且重写Comparator接口中的 compare()

2.方法实现:

a.数组:

  		自然排序: Arrays.sort(数组)
  		自定义比较器: Arryas.sort(数组,new Comparator(){}) 			     

b.List:

  		自然排序: Collections.sort(集合)
  		自定义比较器: Collections.sort(集合,new Comparetor(){}) 			

c.Set:

  		自然排序:   new TreeSet();
  		自定义比较器: new TreeSet(new Comparator(){}) 			

d.Map:

  		自然排序:   new TreeMap();
  		自定义比较器: new TreeMap(new Comparator(){})

3.不管什么集合都可以用自然排序 和 自定义比较器排序
JDK默认都是自然排序

5、Map(I) - 映射表

Map是最大的接口,没有父接口,也就是没有继承Iterable接口,就不能是用迭代器的方式进行遍历/迭代
1.Map的格式

  <K,V> -> <key(键) , Value(值)> -> 键值对 	
  key = value / key:value

2.特点:

a.Map是以键值对的形式进行存储 b.key 和 value 都可以使用泛型<k,v>,就意味着所有引用类型都可以放
c.key不允许有重复值,value允许有重复值
d.key 和 value 允许有null值,但是key的null值只能有一个
e.存储时,根据key的hashCode值进行存储,所以是无序的
f.因为key是唯一的,所以可以根据key获取到相对应的value值

3.HashMap©
1)存储过程:

a.通过hashCode方法确定内存中的地址值
b.判断该位置上是否有元素
c.如果没有元素,直接存入
d.如果有元素,使用equals进行判断两个对象是否相等
e.如果相等,新元素将之前的元素进行覆盖
f.如果不相等

在jdk1.7之前,是先挨个遍历链表中的元素,并用equals进行比较两个元素是否相等,如果都不相等则添加到链表头部
在jdk1.8之后,是先挨个遍历链表中的元素,并用equals进行比较两个元素是否相等,如果都不相等则添加到链表尾部

2)内存空间大小

a.默认初始化容量:16
b.要进行扩容时:
如果内存满了再扩容,就会造成效率低下
如果过半就扩容,占用内存
c.加载因子 - 0.75
内存达到75%就进行扩容,扩容为原容量的2倍

在这里插入图片描述

4.HashTable©
5.ConcurrentHashMap©
6.SortedMap(I)

6.遍历方式

方式一:

通过keySet(),获取key值,返回值类型是Set集合,因为key值的特点是唯一
Set set = map.keySet();

方式二:

通过vaules(),获取value值,返回值类型是Collection,value值的特点是可以出现多个
Collection col = map.values()

方式三:

通过entrySet(),获取key 和 value值, 返回值类型是Set类型
但是因为Set只能存一个泛型,所以使用Map的内部接口Entry获取键和值的泛型<k,v>
Set<Map.Entry<K,V>>set = map.entrySet();

*7.HashTable 和HashMap的区别

a.底层实现区别

HashMap类大致相当于Hashtable ,除了它是不同步的,并允许null

b.继承的类的区别

HashTable:Dictionary
HashMap:AbstractMap

c.效率问题区分

线程安不安全
HashTable:synchronized,线程安全。
HashMap:没有synchronized,线程不安全。

d.扩容机制

ashtable中hash数组默认大小是11,增加的方式是 old*2+1。
HashMap中hash数组的默认大小是16,而且一定是2的指数。

*8.HashTable 和HashMap 和 ConcurrentHashMap的区别

a.再加方法中的锁 -> 锁分离技术 b.jdk1.7 -> 数组(segment数组) + 链表(entry数组 ->
锁entry数组数据 -> 可重入锁(Lock))
jdk1.8 -> 数组 + CAS

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值