java集合
1、概述
所有的集合类和集合接口都在java.util包下。
在内存中申请一块空间用来存储数据,在Java中集合就是替换掉定长的数组的一种引用数据类型。
2、集合与数组的区别
长度区别
数组长度固定,定义长了造成内存空间的浪费,定义短了不够用。
集合大小可以变,用多少空间拿多少空间。
内容区别
数组可以存储基本数据类型和引用数据类型
集合中能存储引用数据类型(存储的为对象的内存地址)
list.add(100);//为自动装箱,100为Integer包装的
元素区别
数组中只能存储同一种类型成员
集合中可以存储不同类型数据(一般情况下也只存储同一种类型的数据)
3、集合结构
在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的结构就是数据结构。不同的数据结构,数据存储方式不同。
Collection单列集合
List接口
List接口:元素按进入先后有序保存,元素可重复
- ArrayList:
- 底层数据结构为数组,使用动态数组来存储元素。
- 查询操作效率高,因为可以根据索引直接访问元素。
- 插入与删除操作效率较低,因为需要移动其他元素来填补空缺或腾出位置。
- 线程不安全
- LinkedList:
- 底层数据结构为双向链表,每个节点包含了当前值和指向前后节点的引用。
- 插入与删除操作效率高,因为只需要修改相邻节点的引用即可完成添加或删除操作。
- 查询操作效率较低,因为需要从头或尾开始遍历链表才能找到对应位置的元素。
- 线程不安全
- Vector
- 底层数据结构为数组,使用动态数组来存储元素。
- 查询操作效率高,因为可以根据索引直接访问元素。
- 插入与删除操作效率较低,因为需要移动其他元素来填补空缺或腾出位置。
- 线程安全
三者区别:
1、底层数据结构:ArrayList与Vector为动态数据,LinkedList为链表
-
ArrayList与Vector在创建初始时都会有一个初始的容量,当这个容量被耗尽时就会进行自动扩容
ArrayList与Vector都可以自定义初始空间大小,不同的是,Vector可以定义扩展空间大小,默认扩展量为,ArrayList扩展一倍,
Vector扩展0.5倍
-
LinkedList为双向循环链表,容量随内容改变
2、线程安全性:ArrayList与LinkedList线程不安全,Vector线程安全
- 由于ArrayList与LinkedList没有提供内建的线程同步机制来保证操作的原子性与一致性,Vector使用了synchronized关键字实现了对操作方法的同步访问。
3、应用场景选择:
-
ArrayList插入和删除操作效率相对较低,因为需要移动其他元素来维护连续性。
LinkedList插入和删除操作效率高,因为只需要修改相邻节点的引用即可。
Vector所有方法都是同步的(使用synchronized关键字),可以在多线程环境中安全地使用Vector执行操作。
Set接口
-
HashSet
- HashSet底层是一个HashMap,不允许有重复的值出现,允许有null值存在,HashSet存储的数据是无序的,无法通过索引查找,通过元素内容查找,HashSet线程不安全
- 优点:增删与查询效率高
-
TreeSet
-
可以对元素排序,底层是一个TreeMap,不允许重复的值存在,通过定义排序规则排序。
-
自然排序(元素自身比较规则):
-
实现Comparable接口的CompareTo(升序):方法如果要按照元素的自然顺序进行排序,则被存储在TreeSet中的对象必须实现Comparable接口,并重写
compareTo()
方法。 -
TreeSet<String> treeSet = new TreeSet<>(); treeSet.add("apple"); treeSet.add("banana"); treeSet.add("cherry"); for (String fruit : treeSet) { System.out.println(fruit); } /*输出:apple,banana,cherry*/
-
-
定制排序(通过比较器指定比较规则):
-
实现Comparator接口的compare方法:如果希望使用一种非自然顺序来进行排序,可以通过创建Comparator对象并传递给TreeSet构造函数来实现。
-
TreeSet<Integer> numberSet = new TreeSet<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 按降序排列 return o2.compareTo(o1); // 按升序排列 // return o1.compareTo(o2); } }); numberSed.add(5); numberSed.add(3); numberSed.add(7); for (Integer num : numberSet) { System.out.println(num); } /*输出:7,5,3*/
-
-
-
Map双列集合
双列集合,用来储存键值对的集合 interface Map<K,V>:K(key键),V(value值)
Map中的键是不能重复的
HasMap:
- 底层数据结构:在HashMap中数据通过数组与链表/红黑树实现对元素的存储,这个数组被称为"散列表",其中每个元素被成为"桶",
- 插入数据过程:计算给定key的hash值,并通过hashCode()方法得到索引位置。如果该位置上未发生哈希冲突,则直接将Entry插入该位置。如果该位置已经存在元素,则遍历链表(或红黑树),如果找到相同的key则更新value;如果没有找到,则添加新节点至末尾或者利用红黑树特性进行插入。链表长度达到阈值8时将链表转化为红黑树(HashMap采用JDK 1.8+版本后才有此优化)。
- 查询数据过程:根据给定key计算hash值及索引位置。判断改索引处是否有元素:若无则返回null;若有,则遍历链表(或红黑树)找到匹配的key并返回value。
TreeMap:
- 一种有序键值映射集合,它基于红黑树(Red-Black Tree)实现。与HashMap不同,TreeMap可以保持键的有序状态。