集合总结的笔记

集合

首先就是集合和数组的区别

1、长度可变性:数组定义时需要指定长度,长度不可变;集合定义时不需要指定长度,长度可变。

2、存放的数据类型:数组可以存放基本数据类型的数据也可以存放引用数据类型的数据;集合只能存放引用数据类型的数据(但是基本数据类型可以自动装箱为引用数据类型,然后存进去)。

3、元素类型:数组在定义时需要指定元素类型,定义后数组只能存放该数据类型的数据;集合定义时可以不指定数据类型,可以存放不同引用数据类型的数据。

集合分类

Collection 单列集合的顶层接口
├——-List 接口:元素按进入先后有序保存;可重复;可以通过索引直接获取元素get(index)
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ StackVector类的实现类,是一个先进后出的栈
└——-Set 接口: 无序;不可重复;不能通过索引获取元素
├—————-└HashSet Set的实现类 使用hash表(数组)存储元素
│————————└ **LinkedHashSet ** 是HashSet的子类 链表,维护元素的插入次序
└ —————-TreeSet 实现类 底层实现为二叉树,元素排好序

Map 双列集合的顶层接口,存放的是键值对
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap

Collection集合的方法

1、boolean add(E e) 在集合末尾添加元素

2、boolean remove(Object o) 若集合中有元素o则删除o并返回true,否则返回false

3、void clear() 清空集合,执行此方法后集合为空

4、boolean contains(Object o) 判断集合中是否包含元素o,有返回true,无返回false

5、boolean isEmpty() 判断集合是否为空,是true,不是false

6、int size() 返回集合中元素的个数

7、boolean addAll(Collection c) 将集合c的所有元素添加到该集合中

8、Object[] toArray() 返回一个包含了该集合所有元素的数组,数组类型为Object[]

9、Iteartor iteartor() 迭代器,集合的专用遍历方式

List

1、ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素。

特有的功能:没有,但是他最常用

2、LinkedList:底层数据结构是双向链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素。

特有的功能:

1)添加:addFirst() addLast()

2)删除:removeFirst() removeLast()

3)获取:getFirst() getLast()

这些方法可以实现将LinkedList作为堆栈或队列使用。

3、Vector: 底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素。

特有功能:

1)addElement(E obj) 相当于add()

2)elementAt(int index)相当于get()

  1. Enumeration elements() 迭代器
Set

1、HashSet:底层数据结构是用哈希表实现的,是数组和链表,元素无序且唯一,线程不安全,效率高,可以存储null元素。元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。HashSet的底层是HashMap,用的HashMap的Key来存储数据,Value是final修饰的静态Object类型的present,present是一个空的Object对象。

具体实现唯一性的比较过程:存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,然后和已经存储的元素的hashCode值比较,如果hashCode不相等,则所存储的两个对象一定不相等,此时存储当前的新的hashCode值处的元素对象;如果hashCode相等,存储元素的对象还是不一定相等,此时会调用equals()方法判断两个对象的内容是否相等,如果返回true,那么就是同一个对象,无需存储;如果返回false,那么就是不同的对象,就该存储了,此时就要采用哈希的解决地址冲突算法,在当前hashCode值处类似一个新的链表, 在同一个hashCode值的后面位置存储不同的对象,这样就保证了元素的唯一性。.

Set添加数据时调用add()方法,实际上是在底层调用Map的put()方法,先使用hashcode()方法得出int类型的hash散列值,如果hash值不相等,说明不是同一对象,直接加进去;如果hash值相同,再调用equals方法判断,如果返回true,则不加,返回false,就在该hach值位置处创建一个链表,链表中装hash值相同equals判断为fals的数据;如果链表长度等于8时,该集合会进行扩容为2倍,如果集合长度为64时,链表会变成红黑树。

重写HashCode()方法的原则:

1)一定要让那些我们认为相同的对象返回相同的hashCode值
2)尽量让那些我们认为不同的对象返回不同的hashCode值,否则,就会增加冲突的概率。
3)尽量的让hashCode值散列开(两值用异或运算可使结果的范围更广)

2、LinkedHashSet:是HashSet的子类,底层数据结构是链表和哈希表共同实现的,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。

3、TreeSet:底层数据结构是二叉树,元素唯一且已经排好序;**实现排序的方式是add元素的时候底层其实调用的map的put方法,在put的时候会将进来的元素按左子树比右子树小的规则放置。**唯一性同样需要重写hashcode()和equals(),二叉树保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;比较器需要在TreeSet初始化的时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;

总结:Set具有和Collection完全一样的接口,因此没有任何额外的功能。实际上set就是collection,只是行为不同,这是继承与多态的典型应用。set不保存重复的元素。

List和Set总结

(1)List,Set都是继承自Collection接口,Map则不是
(2)List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
(3)Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
(4)ArrayList与LinkedList的区别和适用场景
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

LinkedList:
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
适用场景分析:
当需要对数据进行多次访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

ArrayList和Vector的区别

ArrayList有三个构造方法:

public ArrayList(int initialCapacity)//构造一个具有指定初始容量的空列表。    
public ArrayList()      //默认构造一个初始容量为10的空列表。    
public ArrayList(Collection<? extends E> c)//构造一个包含指定 collection 的元素的列表

Vector有四个构造方法:

public Vector()//使用指定的初始容量和等于0的容量增量构造一个空向量。    
public Vector(int initialCapacity)//构造一个空向量,使其内部数据数组的大小,其标准容量增量为零。    
public Vector(Collection<? extends E> c)//构造一个包含指定 collection 中的元素的向量    
public Vector(int initialCapacity,int capacityIncrement)//使用指定的初始容量和容量增量构造一个空的向量 

ArrayList和Vector都是用数组实现的,主要有这么三个区别:
(1)Vector是多线程安全的,线程安全就是说多线程访问同一代码,不会产生不确定的结果。而ArrayList不是,这个可以从源码中看出,Vector类中的方法很多有synchronized进行修饰,这样就导致了Vector在效率上无法与ArrayList相比;
(2)两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同。Arraylist扩容时,默认增长0.5倍;Vector扩容时默认增长1倍。
(3)Vector可以设置增长因子,而ArrayList不可以。
(4)Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。
适用场景分析:
1.Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。
2.如果集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有一定的优势。

HashSet和TreeSet的区别

1.TreeSet 是二叉树(红黑树的树数据结构)实现的,TreeSet中的数据是自动排好序的,不允许放入null值
2.HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
3.HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例

适用场景分析:HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。

Map

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。

注意:Map没有继承Collection接口,它和Collention接口平级。一个 Map 中不能包含相同的 key ,每个 key 只能映射一个 value 。 Map 接口提供 3 种集合的视图, Map 的内容可以被当作一组 key 集合,一组 value 集合,或者一组 key-value 映射。

Map主要方法:

void clear(): 清空集合

boolean containsKey(Object key): 查询Map中是否包含指定key,如果包含则返回true,否则返回false

boolean containsValue(Object value):查询Map中是否包含指定value,如果包含则返回true,否则返回false

Set entrySet():返回Map中所包含的键值对所组成的Set集合,每个集合元素都是Map.Entry对象(Entry是Map的内部类)

Object get(Object key):返回指定key所对应的value,如果没有指定key则返回null

boolean isEmpty():

Set keySet():返回Map中所有key组成的set集合

Collection values():返回该Map中所有value组成的Collection集合

Object put(Object key,Object value):添加一个键值对,如果已有该key,则用新value覆盖该key对应的value

void putAll(Map m):将指定Map中的键值对全部复制到该Map中

Object remove(Object key):删除指定key对应的键值对,返回该key关联的value,如果key不存在,返回null

int size():返回该Map里的键值对个数

内部类Entry:

Object getKey():返回该Entry里包含的key值

Object getValue():返回该Entry里包含的value值

Object setValue():设置该Entry里包含的value值,并返回新设置的value值

HashMap和HashTable的比较

HashMap初始化容量为16,默认加载因子是0.75,也就是集合用量达到容量的百分之75之后就进行扩容,扩容大小为原来容量的2倍。

HashTable初始化容量为11,扩容是原容量的2倍+1。

为什么要有扩容因子

当进行多线程操作时,有可能会一下子加入好几条数据,造成瞬间的空间够的问题。

TreeMap:

在这里插入图片描述

Map的其它类

IdentityHashMap和HashMap的具体区别,IdentityHashMap使用 == 判断两个key是否相等,而HashMap使用的是equals方法比较key值。有什么区别呢?
对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等; 如果作用于引用类型的变量,则比较的是所指向的对象的地址。
对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

Map总结

HashMap 非线程安全
HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。

适用场景分析:
HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap允许空键值,而HashTable不允许。

HashMap:适用于Map中插入、删除和定位元素。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

线程安全的Map:

HashTable

SynchronizedMap:它其实就是加了一个对象锁,每次操作hashmap都需要先获取这个对象锁,这个对象锁有加了synchronized修饰,锁性能跟hashtable差不多。

ConcurrentHashMap

这个是目前使用最多,而且也是最推荐的一个集合,实现也是比较复杂的一个。我们看源码其实是可以发现里面的线程安全是通过cas+synchronized+volatile来实现的,其中也可看出它的锁是分段锁,所以它的性能相对来说是比较好的。整体实现还是比较复杂的。

线程安全集合类与非线程安全集合类

LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable、SynchronizedMap、ConcurrentHashMap是线程安全的;
StringBuilder是非线程安全的,StringBuffer是线程安全的。

数据结构

ArrayXxx:底层数据结构是数组,查询快,增删慢
LinkedXxx:底层数据结构是链表,查询慢,增删快
HashXxx:底层数据结构是哈希表,也是就数组和链表。依赖两个方法:hashCode()和equals()
TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序

红黑树

Red—Black Tree,是一种特殊的二叉查找树红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。

红黑树的特性:

(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

注意
(01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
(02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。

[外链图片转存中...(img-oRwlfHIu-1626696469595)]

红黑树的应用比较广泛,主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。
例如,Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值