导语
集合其实就是一个可以自动扩容的数组,它有一个默认长度,List的默认长度是10,增长因子是0.5;Set,Map默认长度为16,增长因子为0.75。但他们的具体原理又不一样,实现类也不一样,接下来,让我们一起去回顾一下吧!
List
首先它的实现类有:arraylist,LinkedList,Vector,CopyOnWriteArrayList。
arraylist是list最常用的实现类,但它其实是线程不安全的,但是是放在类变量的时候是不安全的,如果作为成员变量,方法变量其实安全的,因为这不存在线程安全不安全的问题。array list的内部就是封装好的数组, 所以它额随机访问速度在list中是最快的,但如果是集合的使用的话,如果它的数据访问量较小,那么list的随机访问速度要快,如果是数据的访问量大的话,HashMap 的访问速度肯要比array list要快。
在这里我们在回顾一下我们的list删除的时候要注意的点
package com.zking.test;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.junit.Before;import org.junit.Test;public class Tesylist {List<Integer> list;@Beforepublic void setup() {list = new ArrayList<Integer>();list.add(1);list.add(4);list.add(8);list.add(8);list.add(12);list.add(16);}/*** 删除元素为8的元素*/@Testpublic void listDel01() {for (int i = 0; i < list.size(); i++) {if (list.get(i) == 8)list.remove(i);}System.out.println(list);// 结果:[1,4,8,12,16],这种方式直接找到第一个元素8,找到后直接删除结束}@Testpublic void listDel02() {for (int i = 0; i < list.size(); i++) {if (list.get(i) == 8)list.remove(i--);}System.out.println(list);// 结果:[1,4,12,16] 这种方式找到第一个8 删除,但第二个8同时发生移位,// 直接跳到第一个8 的位置,但此时指针还未移动,所以又删除一个8 后才往下据继续移动}@Testpublic void listDel03() {for (int i = list.size() - 1; i >= 0; i--) {if (list.get(i) == 8) {list.remove(i);}}System.out.println(list);// 结果:[1,4,12,16] 这种方式是将集合到过来进行遍历删除,第二个8发生移位但又移动// 到了指针还为移动位置,然后删除了}@Testpublic void listDel04() {for (Integer i : list) {if (i == 8)list.remove(i);}System.out.println(list);// 结果:执行错误}@Testpublic void listDel05() {Iterator<Integer> it = list.iterator();while (it.hasNext()) {if (it.next() == 8) {it.remove();}}System.out.println(list);// 结果:[1,4,12,16]迭代器}@Testpublic void listDel06() {Iterator<Integer> it = list.iterator();while (it.hasNext()) {Integer value = it.next();if (value == 8) {list.remove(value);}}System.out.println(list);// 结果:执行不通过}@Testpublic void listDel07() {//ist.add(1);//list.add(4);//list.add(8);//list.add(8);//list.add(12);//list.add(16);list.add(4);// 结果: [1,4,8,12,16],在这里,删除的是下标为4的元素,刚好为元素8list.remove(Integer.valueOf(4));System.out.println(list);//结果: [1,8,8,12,16],在这里,删除的是元素为4的元素,以为通过//integer.valueof()将4转成了一个对象4,所以删除的是4而不是下标为4的元素}}
说完这个array list,我们在来说一下这个其他的实现类
LinkedList
1. linkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部
2. 线程不安全
3. LinkedList可被用作堆栈(stack)【包括了push,pop方法】,队列(queue)或双向队列(deque)
4. 以双向链表实现,链表无容量限制,允许元素为null,线程不安全
5. 适合做随机的增加或删除
Vector
1.线程安全
2.并行性能慢,不建议使用
CopyOnWriteArrayList
这个实现类有点意思,因为它是采用的是写实复制的一种最终一致性的实现类,它线程安全,性能比vector的高。
1.写时复制
2. 线程安全
3. 适合于读多,写少的场景
4. 写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
5. 比Vector性能高
6.最终一致性
7.实现了List接口,使用方式与ArrayList类似
缺点:要等数据修改完了之后才能读取到,在修改数据时别人无法读取新数据,但值得一提的是在在复制和替换的时候这个时间是非常短的,所以我们也可以放心大胆使用。
这里提供一个详细的李斯特讲解的博客
李斯特详解/weixin_67150631/article/details/125475936
Set
和list不一样
1.特点:无序,不重复
2.遍历:foreach,迭代器
3.扩容: 初始容量16,负载因子0.75,扩容增量1倍
李斯特可以重复元素,然后又顺序,但按list的内容进行删除的时候如果不注意可能会出现问题,在这里我也提供一个链接,介绍了set和List为什么删除会出错的原因
Set详解/weixin_67150631/article/details/125491767
Set的实现类
HashSet
1.它存储唯一元素并允许空值,依据对象的hashcode来确定该元素是否存在
2. 由HashMap支持
3. 不保持插入顺序
4. 非线程安全
5. 性能参数:初始容量,负载因子,默认值: 初始容量16,负载因子0.75,示例:new HashSet<>(20, 0.5f);
TreeSet
1.是一个包含有序的且没有重复元素的集合
2.作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序
3.TreeSet是基于TreeMap实现的
Set中的比较器
1.默认自然排序
2.自定义排序
--1. 较器通过构造函数传入比
--2.实现排序接口
这俩种排序方法在上面的连接中有详细介绍,我就不多介绍了
小结:Set和list都是继承的 Collection接口,而下面讲的Map却是继承单独的Map接口。
Map
特点:
1.无序,键值对,键不能重复,值可以重复,这里的无序指的也是插入的顺序和读取的顺序是不一样的,和set集合一样。
2. 键重复则覆盖,没有继承Collection接口,它单独继承Map接口,和list,set不一样,这两个继承collection接口
扩容:
初始容量16,负载因子0.75,扩容增量1倍
遍历:
先获取所有键的Set集合,再遍历(通过键获取值)取出保存所有Entry的Set,再遍历此Set即可。
实现类:
HashMap,HashTable,ConcurrentHashMap,TreeMap,LinkedHashMap
最有意思的是这HashMap,因为它的底层原理可以说是链表结构加红黑树的结构,当你的数据没有超过8的时候,在hashmap桶中就会是一个链结构,当你数据超过8了,你的数据结构就会变成一个红黑数的结构来存储,这样的结构在我们读取数据的时候会更快。
HashMap
1.线程不安全,最常用,速度快
2.内部采用数组来存放数据
HashTable
线程安全,不太常用,与vector类似,将所有数据加一把锁,性能很高
ConcurrentHashMap
线程安全,比HashTable性能高,jdk1.8之前采用16把分段锁,将数据加锁,jdk1.8之后是每一个在数组的桶加锁,每一个桶一把锁,有多少桶就加多少锁,中间在赋值的时候才用的是cas,比较并替换。
TreeMap
key值按一定的顺序排序,添加或获取元素时性能较HashMap慢,因为需求维护内部的红黑树,用于保证key值的顺序
LinkedHashMap
继承HashMap LinkedHashMap是有序的,且默认为插入顺序
当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了
代码实现:
Map<String, String> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("name1", "josan1");linkedHashMap.put("name2", "josan2");linkedHashMap.put("name3", "josan3");Set<Entry<String, String>> set = linkedHashMap.entrySet();Iterator<Entry<String, String>> iterator = set.iterator();while(iterator.hasNext()) {Entry entry = iterator.next();String key = (String) entry.getKey();String value = (String) entry.getValue();System.out.println("key:" + key + ",value:" + value);}
想了解更为详细的Map知识的直接去这里:
Map详解/weixin_67150631/article/details/125511020
总结:
集合的使用在我们编码的过程中可以说是非常的常见,而集合的基本原理也先要我们去好好的了解,不然出Bug了怎么解决,有办法,来看我的博客!!!
欢迎一键三连