集合总结
集合框架
比较常用的几个:
其中Collection接口的实现子类的是单例集合,Map接口实现的子类是双例集合,存放K-V.
Collection 接口和常用方法
1.特点
1) collection实现子类可以存放多个元素,每个元素可以是0bject
2)有些Collection的实现类,可以存放重复的元素,有些不可以
3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
4) Collection接口没有直接的实现子类,是通过它的子接口Set和List来
实现的
2.实现方法
3.遍历方法
1.迭代器遍历
Collection col = new ArrayList();
Iterator iterator = col.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
2.增强for循环遍历
Collection col = new ArrayList();
for (Object o : col) {
System.out.printl(o);
}
3.传统for循环遍历(用list举例)
Collection col = new ArrayList();
for(int i=0;i < list.size();i++){
Object object = list.get(i);
System.out.println(object);
4.List
特点
- List集合类中元素有序,且可重复
- List集合中每个元素都有对应的索引和整数型序号记载在容器的位置
常用方法
1.ArrayList
特点
- ArrayList可以加入多个null,并且可以加入多个
- ArrayList可以存放多个相同的元素
- ArrayList是由数组来实现数据存储
- ArrayList执行效率高,但是线程不安全,在多线程下用Vector代替
- ArrayList维护一个Object类型的数组elementData
- 在创建ArrayList对象时,如果使用的是无参构造器,则elementData的初始容量为0,第一次添加时,elementData的容量扩容为10,再次扩容时,elementData扩容为1.5倍
- 在创建ArrayList对象时,如果使用的是有参构造器,则初始容量为指定的容量,再次扩容时,elementData扩容为1.5倍
常用方法
方法 | 描述 |
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
2.Vector
特点
- Vector底层也是一个Object类型的数组elementData,基本用法等同于ArrayList
- Vector可以存放多个null元素
- Vector是线程安全/线程同步的,在多线程的情况下用Vector而不是ArrayList
- Vector可以存放多个相同的元素
- 在创建Vector对象时,如果使用的是无参构造器,则elementData的初始容量为10,满了之后按两倍扩容
- 在创建Vector对象时,如果使用的是有参构造器,则初始容量为指定的容量,再次扩容时,elementData扩容为2倍
方法
如上ArrartList
3.LinkedList
说明:链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
特点
- LinkedList实现了双向链表和双端队列的特点
- 可以添加多种重复的元素(包括null)
- 线程不安全,没有实现同步
- LinkedList维护的两个属性first和last分别指向头结点和尾结点
-
LinkedList 继承了 AbstractSequentialList 类。
-
LinkedList 实现了 Queue 接口,可作为队列使用。
-
LinkedList 实现了 List 接口,可进行列表的相关操作。
-
LinkedList 实现了 Deque 接口,可作为队列使用。
-
LinkedList 实现了 Cloneable 接口,可实现克隆。
- LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。
常用方法
方法 | 描述 |
---|---|
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
4.ArrayList,Vector,LinkedList的区别
名称 | 底层结构 | 线程安全/效率 | 扩容倍数 | 增删效率 | 改查效率 |
ArrayList | 可变数组 | 不安全/效率高 |
有参:初始指定长度,开始扩容1.5倍 无参:第一次扩容到长度为10,第二次开始扩容1.5倍 |
低 | 高 |
Vector |
可变数组 |
安全/效率低 |
有参:初始指定长度,满后按两倍扩容 无参:初始长度为10.满后按两倍扩容 |
低 | 高 |
LinkedList | 双向链表 | 不安全/效率高 | 没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好。 | 低 | 高 |
5.Set
特点
- 无序性(添加和取出的顺序不一样,但是顺序是固定的 ),没有索引
- 不允许有重复的元素,所以只能有一个null
- 没有索引,不能使用传统for方式来遍历
- Set 具有与 Collection 完全一样的接口,只是行为上不同
常用方法
参考上方Collection的方法,基本一致
1.Hashset
特点
- Hashset实际上就是Hashmap
- Hashset不保证元素是有序的,取决于hash再确定结果
- 不能有重复对象
- HashSet 不是线程安全的
- HashSet的元素实际上是对象
存放机制
扩容机制
- 第一种情况是在长度大于等于8的链表后面加结点,如果数组大小没到64,则继续扩容,并且将此结点添加到链表尾(单条链表没有数量限制,别认为hashset一条链表限制8个元素)
- 第二种情况是看临界值扩容,当我们向 hashset 增加一个元素,-> Node -> 加入 table , 就算是增加了一个 size++,当到了临界值12,再添加一个元素到13的时候,就会触发扩容机制,而不是看table数组有没有用了12个不同的索引。
LinkedHashSet
特点
- 是HastSet的子类
- 底层维护了一个LinkedHashmap,是数组+双向链表
- 根据Hashcode来决定元素的存储位置,同时用一个链表维护次序,使得元素像是是以插入顺序保存的
- 不允许添加重复元素
2.TreeSet
特点
- TreeSet是一个包含有序的且没有重复元素的集合
- TreeSet 继承于AbstractSet,是一个Set集合,具有Set的属性和方法。
- TreeSet 实现了NavigableSet接口,意味着支持一系列的导航方法。比如查找与指定目标最匹配项
- TreeSet 实现了Cloneable接口,意味着它能被克隆。
- TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。
- TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。
Map接口和常用方法
特点
- Map 接口存储一组键值对象,提供key(键)到value(值)的映射。
- Map用于保存具有映射关系的key-value数据
- Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
- Map中的key不允许重复,原因和HashSet 一样
- Map中的value可以重复
- Map的key可以为null, value也可以为null ,注意key为null,只能有一个,value为null ,可以多个.
- 常用String类作为Map的key
- key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
常用方法
- put:添加
- remove:根据键删除映射关系
- get:根据键获取值
- size:获取元素个数
- isEmpty:判断个数是否为0
- clear:清除
- containsKey:查找键是否存在
1.HashMap
特点
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized。
- HashMap的key不能重复,但是值可以重复,允许使用nulI键和nulI值,如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)。
- HashMap 是无序的,即不会记录插入的顺序。
- HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口
- HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
实例
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
常用方法
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
底层扩容机制
2.Hashtable
特点
- 存放的元素是键值对: 即K-V
- hashtable的键和值都不能为null, 否则会抛出NullPointerException
- hashTable使用方法基本上和HashMap-样
- hashTable是线程安全的(synchronized), hashMap是线程不安全的
扩容机制:
- 一开始数组初始为11个。
- threshold为7个。
- 当元素个数大于等于threshold的时候开始扩容。
- 后面扩容是 (oldcapacity *2 +1)
Hashtable和HashMap的区别
Properties
特点
- Properties类继承自Hashtable类并且实现了 Map接口,也是使用-种键值对的形
式来保存数据。 - 他的使用特点和Hashtable类似
- Properties 还可以用于从xxx.properties文件中,加载数据到Properties类对象,
并进行读取和修改 - 说明:工作后xxx.properties 文件通常作为配置文件
3.TreeMap
- TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。
- TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。
- TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。
- TreeMap 实现了Cloneable接口,意味着它能被克隆。
- TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。
- TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的
- Comparator 进行排序,具体取决于使用的构造方法。
- TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。
- 另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。
- 由于TreeMap中的元素是从小到大的顺序排列的。因此,顺序遍历,就是从第一个元素开始,逐个向后遍历;而倒序遍历则恰恰相反,它是从最后一个元素开始,逐个往前遍历。
- TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
- TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n)。
开发中如何选择集合类
Collections 工具类
实例
package com.hspedu.collections_;
import java.util.*;
@SuppressWarnings({"all"})
public class Collections_ {
public static void main(String[] args) {
//创建ArrayList 集合,用于测试.
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
list.add("tom");
// reverse(List):反转 List 中元素的顺序
Collections.reverse(list);
System.out.println("list=" + list);
// shuffle(List):对 List 集合元素进行随机排序
// for (int i = 0; i < 5; i++) {
// Collections.shuffle(list);
// System.out.println("list=" + list);
// }
// sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
Collections.sort(list);
System.out.println("自然排序后");
System.out.println("list=" + list);
// sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
//我们希望按照 字符串的长度大小排序
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//可以加入校验代码.
return ((String) o2).length() - ((String) o1).length();//List允许重复,所以能同时有两个长度相同的
}
});
System.out.println("字符串长度大小排序=" + list);
// swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
//比如
Collections.swap(list, 0, 1);
System.out.println("交换后的情况");
System.out.println("list=" + list);
//Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
System.out.println("自然顺序最大元素=" + Collections.max(list));
//Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
//比如,我们要返回长度最大的元素
Object maxObject = Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length() - ((String)o2).length();
}
});
System.out.println("长度最大的元素=" + maxObject);
//Object min(Collection)
//Object min(Collection,Comparator)
//上面的两个方法,参考max即可
//int frequency(Collection,Object):返回指定集合中指定元素的出现次数
System.out.println("tom出现的次数=" + Collections.frequency(list, "tom"));
//void copy(List dest,List src):将src中的内容复制到dest中
ArrayList dest = new ArrayList();
//为了完成一个完整拷贝,我们需要先给dest 赋值,大小和list.size()一样
for(int i = 0; i < list.size(); i++) {
dest.add("");
}
//注意:size是指元素个数,而length是数组长度,构造器是不会改变size的。不能通过初始化集合来给定大小,因为这并不会改变size,底层是用两个集合的size比较的,size 和 length 不能等同,size 表示 当前集合的元素个数, 随着元素的增加而增加。
//拷贝
Collections.copy(dest, list);
System.out.println("dest=" + dest);
//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
//如果list中,有tom 就替换成 汤姆
Collections.replaceAll(list, "tom", "汤姆");
System.out.println("list替换后=" + list);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码