Java集合整理

集合类
在这里插入图片描述

集合(Collection)
1、 List列表 : 有序 可重复

类型描述
ArrayList数组列表 ,内部是通过Array实现,对数据列表进行插入、删除操作时都需要对数组进行拷贝并重排序,因此在知道存储数据量时,尽量初始化初始容量,提升性能 。
LinkedList双向链表 每个元素都有指向前后元素的指针,顺序读取的效率较高,随机读取的效率较低
Vector向量 ,类中的方法很多有 synchronized 进行修饰,以保证线程安全,与ArrayList 一样也是通过数组实现的
Stack栈 , 后进先出 LIFO , 继承自Vector,也是用数组,线程安全的栈
类型底层实现线程安全扩容方式特点
ArrayList数组默认容量是 10,扩容为1.5倍查询快,增删慢
LinkedList链表没有扩容的机制查询慢,增删快
Vector数组默认初始容量为10,扩容为2倍查询快,增删慢

2、Queue队列:有序 可重复

类型描述
ArrayDeque数组实现的的双端队列, 可以在队列两端插入和删除元素
LinkedList也属于双端队列
PriorityQueue优先队列 ,数组实现的二叉树, 完全二叉树实现的小顶堆(可改变比较方法)

3、Set集合: 无序 不重复
无序性是指存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定
不可重复性是指添加的元素按照equals()判断时,返回false。需要重写equals()和hashCode()。

类型描述
HashSet基于哈希表实现,使用散列函数来存储元素
LinkedHashSet继承自 HashSet,使用哈希表和链表实现。
TreeSet红黑树结构
类型底层实现线程安全扩容方式特点
HashSet哈希表添加元素时,table数组扩容为16,负载因子为0.75;临界值(threshold)是(16 * 加载因子(loadFactor)是0.75 )=12无序
LinkedHashSet链表和哈希表,元素插入取出满足FIFO初始容量为16,临界值为12,以后再次扩容,扩容2倍有序
TreeSet底层数据结构是红黑树容量翻倍有序

集合(Collection)和数组的区别
1、数组的长度是固定的,集合长度是可以改变的,提供很多成员方法。
2、数组的存放的类型只能是一种(基本类型/引用类型),集合存放的类型可以不是一种(不加泛型时添加的类型是Object)。(当将元素放入集合时,它们会被转换成Object类型,之后在访问集合中的元素时需要进行强制类型转换。这种设计虽然方便,但也带来了类型不安全的隐患,以及类型转换的性能损失。)
3、数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查都是最快的。

工具

遍历集合:Iterator 和 Enumeration
操作集合:Arrays 和 Collections

Map

类型KeyValue描述
Hashtable不允许为null不允许为null线程安全
HashMap允许为null允许为null哈希映射 无序 , key 和 value 都可以为null
TreeMap不允许为null允许为null红黑树实现的, 可排序, 红黑树是一种自平衡二叉查找树
CocurrentHashMap不允许为null不允许为nullSegments数组+ReentrantHashMap(作为互斥锁来控制并发访问)+链表
类型底层实现线程安全扩容方式特点
HashMap数组+(当链表大于等于8且数组长度大于等于64)红黑树初始容量是 16,临界值是(16 * 加载因子0.75 )=12,当元素个数达到12时扩容为2倍无序集合
LinkedHashMap基于HashMap,并自己维持了一个双向链表,按照插入顺序进行访问,实现了LRU算法初始容量是 16,2倍扩容有序集合
CocurrentHashMapSegments数组+ReentrantHashMap(作为互斥锁来控制并发访问)+链表,采用分段锁保证安全链表元素超8个,数组大小超64,转红黑树无序集合,性能比HashTable好
HashTable数组+链表初始大小为11,扩容为2n+1无序集合
TreeMap基于红黑树2倍有序集合

List:有序、可重复。
Set:无序、不可重复的集合。重复元素会覆盖掉。
Map:键值对,键唯一、值不唯一。Map 集合中存储的是键值对,键不能重复,值可以重复。

LinkedHashMap
LinkedHashMap继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题。在一些场景下,该特性很有用,比如缓存。
在这里插入图片描述

hashMap和LinkedHashMap区别

  • 插入顺序:HashMap不保证映射的顺序,而LinkedHashMap会根据元素插入的顺序维护一个双向链表,因此保证了映射的顺序,可以通过get操作访问元素的插入顺序。
  • 迭代顺序:LinkedHashMap迭代元素的顺序是插入顺序,而HashMap的迭代顺序是随机的。
  • 性能:由于LinkedHashMap在底层额外维护了一个双向链表,因此在插入或删除元素时需要更多的操作,因此LinkedHashMap的性能通常比HashMap要低,内存占用通常比HashMap要高一些。

hashMap和TreeMap区别

  • 插入顺序:HashMap不保证映射的顺序,而TreeMap会根据元素的键值进行排序,因此保证了映射的顺序。
  • 元素访问时间复杂度:HashMap的元素访问时间复杂度是常数级别的,即O(1),而TreeMap的元素访问时间复杂度是基于红黑树的复杂度,通常是O(log(n))。
  • 键的类型:HashMap可以使用任何类型的对象作为键,只要它们能正确的实现hashCode()和equals()方法,而TreeMap的键必须实现Comparable接口或提供自定义的Comparator比较器来进行比较。
  • 内存占用:由于TreeMap需要维护红黑树的结构,因此它的内存占用相对较高。而HashMap在元素较少时,占用内存较小。

HashMap原理

  • HashMap在Jdk1.8以后是基于数组+链表+红黑树来实现的,特点是,key不能重复,可以为null,线程不安全

  • HashMap的扩容机制:HashMap的默认容量为16,默认的负载因子为0.75,当HashMap中元素个数超过容量乘以负载因子的个数时,就创建一个大小为前一次两倍的新数组,再将原来数组中的数据复制到新数组中。当数组长度到达64且链表长度大于8时,链表转为红黑树

  • HashMap存取原理:
    (1)计算key的hash值,然后进行二次hash,根据二次hash结果找到对应的索引位置
    (2)如果这个位置有值,先进性equals比较,若结果为true则取代该元素,若结果为false,就使用高低位平移法将节点插入链表

  • 为什么不一开始就使用红黑树?
    ​ 因为直接采用红黑树的话每次加入元素需要进行平衡,而在超过8时再旋转变为红黑树可以达成平衡,因为大部分哈希槽的元素个数正态分布在8个左右,所以此时变为红黑树也满足了查找的效率。

想要线程安全的哈希表
(1)使用ConcurrentHashMap
(2)使用HashTable
(3)Collections.synchronizedHashMap()方法

hash表:
构造:① 直接定址法;②平方取中法;③折叠法;④除留取余法
冲突解决:① 开放定址法(线性探测)② 链地址法

HashTable与HashMap的区别

  • (1)HashTable的每个方法都用synchronized修饰,因此是线程安全的,但同时读写效率很低

  • (2)HashTable的Key和Value不允许为null,HashMap的Key和Value允许为null

  • (3)HashTable只对key进行一次hash,HashMap进行了两次Hash

  • (4)HashTable底层使用的数组加链表,HashMap 数组链表加红黑树(当链表大于等于8且数组长度大于等于64,链表转红黑树)

ConcurrenHashMap与HashTable的区别

ConcurrentHashMap性能更高,它基于分段锁+CAS 保证线程安全,分段锁基于 synchronized 实现,它仅仅锁住某个数组的某个槽位,而不是整个数组

  • ConcurrentHashMap 没有大量使用 synchronsize 这种重量级锁。而是在一些关键位置使用乐观锁(CAS), 线程可以无阻塞的运行。
  • ConcurrentHashMap读方法没有加锁
  • ConcurrentHashMap扩容时老数据的转移是并发执行的,这样扩容的效率更高。

ArrayList和LinkedList的区别

  • ArratList的底层使用动态数组,默认容量为10,当元素数量到达容量时,生成一个新的数组,大小为前一次的1.5倍,然后将原来的数组copy过来;因为数组有索引,所以ArrayList查找数据更快,但是添加数据效率更低

  • LinkedList的底层使用链表,在内存中是离散的,没有扩容机制;LinkedList在查找数据时需要从头遍历,所以查找慢,但是添加数据效率更高

如何保证ArrayList的线程安全?
(1)使用collentions.synchronizedList()方法为ArrayList加锁
(2)使用Vector,Vector底层与Arraylist相同,但是每个方法都由synchronized修饰,速度很慢

在Queue接口中, poll() 和 remove() 方法都用于从队列中移除并返回队头的元素。
如果队列为空,即没有元素可供移除时, pol0 方法会返回null。它是一个安全的方法不会抛出异常。
remove()在没有元素可供移除时,会抛出NoSuchElementException 异常。

怎么确保集合不可更改?
Java 集合框架提供了一些不可变集合类,如不可变列表(ImmutableList)、不可变集合(ImmutableSet)和不可变映射(ImmutableMap)。

List list = ImmutableList.of(“a”, “b”, “c”);
Set set = ImmutableSet.of(“x”, “y”, “z”);
Map<String, Integer> map = ImmutableMap.of(“a”, 1, “b”, 2, “c”, 3);
List list2 = ImmutableList.builder().addAll(list1).add(“d”).build();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值