集合类
个人结合所学知识整理,如有错误理解敬请指正,感谢🙏
Collection容器
1.Collection和Collections
- Collection是所有数组和链表类的顶级接口,List和Set是它的直接子类,Collection接口提供了对集合对象进行基本操作的通用接口方法,它的意义是为各种具体的集合提供最大化的统一操作方式
- Collections是一个包装类,不能被实例化。它包含很多有关集合操作的静态多态方法,包括排序、搜索、线程安全等,是一个服务于JavaCollection集合的工具类
2.Java中常用的Collection集合类
- Java常用的Collection集合类有ArrayList、LinkedList、CopyOnWriteArrayList、Vector、HashSet、LinkedHashSet、TreeSet等
- 上述常用Collection集合类除了CopyOnWriteArrayList和Vector以外都是非线程安全的
3.List集合
ArrayList
-
介绍: ArrayList是最常见的List实现类,线程不安全,内部是通过数组实现,它的优点是可以通过下标对元素进行快速随机访问,缺点是存入的元素是连续而无间隔的,当数组容量不够时需要重新复制到一个更大容量的数组中,往数组中间插入或删除元素时,也需要对后续元素进行移位,这会复制移动的操作会导致效率降低。因此ArrayList适合随机查找和遍历,不适合插入和删除操作
-
底层实现: ArrayList的底层实现是一个Object[]数组,查找元素时时间复杂度为O(1),尾部插入或删除元素时时间复杂度为O(1),中间插入或删除元素时时间复杂度为O(n-i)
-
==扩容机制:==以无参构造创建的ArrayList是一个空数组,当存入第一个元素时,数组容量会扩为10,当10个容量全部用完后不会立即扩容,而是在存入第11个元素时将数组扩容1.5倍,即创建一个容量为15的新数组,然后将旧数组元素拷贝过来
-
常用方法:
//创建 List list = new ArrayList(); //添加元素 list.add("item1"); list.add("item2") list.add("item3");//输出数组: [item1, item2, item3] //查找元素 list.get(1);//输出: item2 //修改元素 list.set(0, "setItem1");//get(0)输出:setItem1 //删除元素 list.remove(0);//输出数组:[item2, item3] //计算数组大小 list.size();//结果:2 ...
-
遍历方式:
List list = new ArrayList(); list.add("item1"); list.add("item2") list.add("item3"); //遍历 for (String i : list) { System.out.print(i + " "); } //输出:item1 item2 item3
LinkedList
-
介绍: LinkedList与ArrayList不同,它是一个链表,不支持高效的随机访问,在增删元素时不受元素位置影响,时间复杂度近似O(1),但如果需要在指定位置增删元素,则需要先移动到指定的位置,时间复杂度为O(n)。
-
底层实现: 在Jdk1.6之前为循环链表,Jdk1.7取消了循环,改为双向链表。LinkedList将存入的元素包装为Node节点,将元素的原对象用赋值给element成员,并没有改变原来的对象。
-
扩容机制: LinkedList初始容量为0,扩容时只需要新建节并改变指针指向即可
-
遍历方式:
LinkedList<String> sites = new LinkedList<String>(); sites.add("Google"); sites.add("Runoob"); sites.add("Taobao"); sites.add("Weibo"); for (String i : sites) { System.out.println(i); }
Vector
- 介绍: Vector是很久的list实现类,是一个线程安全的动态数组
- 底层实现: 底层是一个动态数组,和ArrayList类似但是不同,它提供的很多传统的方法都不属于集合框架,且Vector类中的方法都有synchronized关键字修饰,其中的单个方法都属于原子操作,是线程安全的,因此效率比ArrayList低
- 扩容机制: 无参构造创建的Vector初始容量为10,每次扩容一倍长度
- 遍历方式: 与ArrayList相同
4.Set集合
HashSet
-
介绍: HashSet是基于HashMap实现的无序不可重复的集合,允许空值但只能有一个,线程不安全
-
底层实现: HashSet底层是一个HashMap,但HashSet存入元素时只存入key,value的位置是一个PRESENT常量,由于存入时会计算hash值确定位置,而同一个hash值对应的Entry数组可能会有多个元素,因此HashSet在遍历元素时是无序的
//java中的Hashset实现 private transient HashMap map; // Constructor - 1 // All the constructors are internally creating HashMap Object. public HashSet() { // Creating internally backing HashMap object map = new HashMap(); } // Constructor - 2 public HashSet(int initialCapacity) { // Creating internally backing HashMap object map = new HashMap(initialCapacity); } // Dummy value to associate with an Object in Map private static final Object PRESENT = new Object(); //add方法: public boolean add(E e) { return map.put(e, PRESENT) == null; }
-
扩容机制: HashSet无参构造创建一个初始容量为16的HashMap,负载因子为0.75,即当存入12个元素后,HashMap会扩容。
-
常用方法: add()、remove()、contains()、isEmpty()、size()
-
遍历方式:
HashSet<String> hs = new HashSet<String>(); hs.add("Geek"); hs.add("For"); hs.add("Geeks"); //迭代器遍历 Iterator itr = hs.iterator(); while (itr.hasNext()){ System.out.print(itr.next() + ", "); } //for each遍历 for (String s : hs){ System.out