Java集合框架

第一章 集合框架

1.1集合(Collection)体系结构

Collection接口:它是Java集合体系结构的根接口。

描述的是元素独立的集合。有的集合可以允许元素重复。有的集合是有序的(前后顺序)

子接口:

List接口:元素有顺序。

ArrayList

LinkedList

Vector

Set接口:元素不能重复。

HashSet

LinkedHashSet

TreeSet

Queue接口:队列。

DeQue接口:双端队列。

Map接口:是一种哈希的实现。

每一个元素,都由两部分组成:键(key)-值(value),称为键值对(key-value);

HashMap

LinkedHashMap

HashTable

TreeMap

ConcurrentMap

请介绍一个Java中的集合?

1.2 List接口

1.2.1特点

有序,所以可以使用下标访问

通常允许重复元素

有的可以使用null,有的不可以

1.2.2常用方法

add

addAll

clear

remove

removAll

set(index,Object)

contains

get(index)

size()

isEmpty()

indexOf();

lastIndexOf()

subList()

1.2.3ArrayList类

这是一个可变数组。长度是可以变化的。

底层实现是数组。

特点:

  1. 通过下标访问时,速度很快!可以通过起始地址+下标偏移量直接计算出元素的位置,时间复杂度O(1)
  2. 在中间位置插入和删除元素时,需要将指定位置后的元素进行移动。这时的效率很低,时间复杂度O(n)
  3. 在尾部插入和删除元素,效率也很高。

什么情况下使用ArrayList???

查询操作多,从中间插入或删除的操作少。

默认初始容量是10

扩容时,扩充为原来容量的1.5倍,如果还不够用需要多少扩充多少

1.2.4LinkedList类

长度也是可以变化的。

底层是一个链表(双向链表)实现的。

什么是链表?

链表示一种数据结构(计算机中对数据进行组织和存储的结构)

根据数据之间的关系进行分类

  1. 元素之间没有任何关系,只存在于一个集合中。
  2. 一对一:一个元素最多只有一个前驱元素,最多只有一个后继元素。

一对一关系称为线性结构

数组:内存连续,大小固定的。

链表:内存不连续。元素包含两部分:值+指针(指向下一个元素)

单链表:只有头,没有尾

双端链表:有头也有尾,尾部追加也很方便

循环链表:尾部元素的指针直接指向第一个元素

双向链表:两套指针,既可以从前往后找,也可以从好后往前找

双向循环链表:既是双向的,也算是循环的

队列:只能在两端进行操作。从一头添加(入队),从另一头取(出队)。先进先出,后进后出

栈:下只能从一端进行操作,先进后出,后进先出。

  1. 一对多:一个元素最多只有一个前驱元素,但可以有多个后继元素。

称为树。

二叉树(满二叉树、完全二叉树、二叉排序树BST、平衡二叉树、平衡二叉排序树AVL、红黑树),B树,B+树,B*树

  1. 多对多:一个元素可以有多个前驱元素,也可以有多个后继元素。

称为图。

有向图和无向图。广度优先遍历、深度优先遍历。

因为使用链表实现的,所以

  1. 根据下标志查找元素的操作效率很低,需要从头一个个遍历元素,O(n)
  2. 如果在中间位置插入或删除元素,效率很高只需要重新设置前后元素的指针即可。

1.2.5Vector类

与ArrayList基本一致。是线程安全的

一般不用。

1.2.6 List集合的遍历

1.循环生成下标

2.增强for循环 foreach

foreach基于迭代器实现

数组在foreach时实现的是for循环

3.Iterator——迭代器

当一个集合元素在进行迭代过程中,不能对原始集合进行添加或删除元素的操作。

可以替换某个元素

迭代器自己可以操作元素,但只能删除当前读到的元素。

总之就是不能改变元素数量!!!(除了iterator.remove)

1.3 set接口

1.3.1特点

不包含重复元素。

有些可以包含null,有些不能

没有前后顺序

1.3.2常用方法

add

addAll

remove

clear

contains

isEmpty

size

1.3.3 HashSet类

不保证迭代顺序

允许null

线程不安全

底层实现是HashMap类的对象。

  1. 构造函数

初始容量:默认是16

加载因子:默认是0.75

也可以指定初始容量和加载因子。

  1. 遍历
  1. foreach
  2. 迭代器

1.3.4 LinkedHashSet类

底层是哈希表+链表实现

链表确定迭代的顺序。就是插入的顺序。先插入的元素遍历时先取出来

1.3.5 TreeSet类

底层是TreeMap,Tree Map的底层是红黑树。

红黑树BST(Binary Sort/Search Tree),这棵树上的元素是有顺序的,他还是一个自平衡的BST,添加或删除节点时,调整树的结构,保持平衡。

平衡二叉树:根节点左右两棵子树高度差不大于1.左右子树也是平衡的。

排序:自然顺序或重写compareTo方法,或Comparator方法。

TreeSet集合中的元素要求必须能够比较大小。

  1. 对象提供对Comparable的接口实现。重写compareTo方法。
  2. 创建TreeSet时,指定一个比较器Comparator,指定元素之间比较大小的方式
  3. A>B B>C  => A>C

1.4Map接口

Map表示一个键和值之间的映射关系。

数组\List集合:通过下标找到元素。

Map集合:通过Key找到元素      键值对

1.4.1特点

特点:

  1. 键不能重复。
  2. 每个键只能有一个值
  3. 里面的元素是键值对映射的

1.4.2哈希表

哈希表:HashTable  键和值之间的映射关系叫做哈希

哈希中的映射关系通过一个哈希函数来进行

将Key通过一定的运算,得到一个哈希码或哈希地址

哈希函数:

  1. 直接定址法:哈希函数为一次函数,H(key)==key或H(key)=a*key+b;

其中H(key)表示关键字为key对应的地址

  1. 数字分析法:有多位字符或数字组成,考虑抽取其中两位或多位作为关键字对应的地址
  2. 平方取中法:对关键字做平方操作,去中间几位作为哈希地址。比较常用
  3. 折叠法:将关键字分割成位数相同的及部分,去及部分叠加和作为哈希地址,适用于关键字位数较多的情况。
  4. 除留余数法:若已知整个哈希表的最大长度m,可以取一个不大于m的数P,然后对关键字做取余运算,P可以为不大于m的质数或者不包含小于20的质因数合数
  5. 随机数法:取关键字关键字的一个随机函数值作为哈希地址,适用于关键字长度不等的情况。

哈希冲突:

  1. 开放地址法:线性探测、二次探测、伪随机数
  2. 再哈希法:再执行另一个哈希函数
  3. 链式地址法:桶+链表
  4. 公共溢出区:

Java用链地址法解决哈希冲突

1.4.3 HashMap类

1.特点:

基于哈希表

允许null和null键

不同步,线程不安全

元素是无序的。

2构造

初始容量:默认是16。也可以单独设置

桶的数量。用来表示桶的数组的长度。

加载因子:默认是0.75。也可以单独设置

用于扩容。当前Map中的元素,当到了当前容量*0.75,此时需要扩容

扩容时,新的容量=老的容量<<1

假设一个HashMap初始容量为16,则达到12时开始扩容,扩容后容量*2,左移一位,扩容为32.

HashMap中的每一个元素都会构造成Node,这些元素都保存在一个Node类型的数组中,这个数组就是桶。

桶中的元素,不是独立的单个元素,而是链表的形式。

当出现哈希冲突时,冲突元素将会与原来的元素组成一个链表。如果链表太长,查找效率就会降低。

HashMap的底层实现

底层由数组+链表+红黑树组成。

为什么要有链表?解决hash冲突,链式地址法

为什么要用红黑树?链表过长,导致效率太低,提高查找效率。

在JDK7以后,当HashMap中的元素数量达到64时,并且链表长度达到8时,链表将转换成红黑树(O(logn)),来提高查询效率。红黑树节点减少到6时,此时会再次转换成链表。红黑树可以通过节点颜色记录一些平衡的信息。

  1. 红黑树

它是一颗自平衡的二叉排序树,性能比AVL高。

通过红黑树的结点颜色,记录一些平衡信息。

特点:

  1. 结点要么是红要么是黑
  2. 根节点是黑色
  3. 叶子结点都是null
  4. 每个红色结点的子结点一定是黑色
  5. 任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

变化:

  1. 插入结点初始都是红色
  2. 根结点是黑色
  3. 当前结点父结点是黑色,这种情况下不会破坏红黑树,不需要进行任何操作
  4. 当前结点父结点是红色的,并且叔叔节点也是红色的,将当前结点父结点和叔叔结点涂黑,祖父节点涂红
  5. 当前结点父结点是红色的,叔叔结点是黑色的(叔叔节点为null):
  1. 父结点是爷爷节点的左结点,当前结点是父结点的左结点(LL)

父结点变黑,爷爷节点变红,爷爷右旋转。

  1. (LR)父结点左旋,在进行LL
  2. RL 父结点右旋,在进行RR
  3. RR  父结点变黑,爷爷节点变红,爷爷节点左旋
  1. 构造方法:

HashMap<键泛型,值泛型> 对象名 = new HashMap<>();

  1. 方法

1)对象名.put(键,值) 添加键值对

2)对象名.clear()   清除所有键值对

3)对象名.replace(键,值)  替换某个键的值

4)对象名.clear()   清除所有键值对

5)对象名.remove()     删除某个键对应的值

6)对象名.get(键)   查询键对应的值

7)对象名.keySet()       查询所有key

8)对象名.values()       查询所有值

9)对象名.entrySet()    查询所有键值对

  1. 遍历

map集合不实现迭代器(Iterator),只能通过间接遍历

1.4.4 Hashtable类

1.特点

不允许使用null值和null键

同步,线程安全

操作方法上都加了synchronized修饰

1.4.5 LinkedHashMap类

基于哈希表+链表。

链表用于保存Key加入的顺序

迭代Key时,会按照加入的顺序进行迭代。

1.4.6 TreeMap类

基于红黑树

TreeMap中的键值对会根据Key的大小进行排序。

Key必须能够比较大小,要么有自然顺序,要么实现了Comparable接口,要么提供Comparetor比较器

ConcurrentHashMap类

基于哈希表的。

Concurrent:同时发生的,并发的。

这是一个线程安全的

Synchronized关键字,锁的是其中的一个Node,其中的一个桶。使用的是分段锁。允许多个线程锁不同的桶,所以效率更高

而HashTable锁的整个Map。使用的全局锁,效率低

1.4.8 Attributes类

1.4.9 Properties类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值