当前位置: 首页 > article >正文

Java 集合框架(Collection)

Java 集合框架(Collection)

Java 集合框架

CollectionMap 是 Java 集合框架中的两个顶层接口

image-20250306223420913

Collection接口

image-20250306223424670

Collection接口的实现类包括 ListSet

  • list系列集合有序、可重复、有索引

  • set系列集合无序、不重复、无索引

    HashSet:无序、不重复、无索引

    LinkedHashSet有序、不重复、无索引

    TreeSet按照大小默认升序排序、不重复、无索引

collection接口公共的方法

add、clear、remove、contains、isEmpty、size、toArray

image-20250306224719274

public Object[] toArray()

Collection中的所有元素转换为一个Object[] 类型的数组

ArrayList 转换为特定类型的数组,可以使用 toArray(T[] a) 方法。这个方法允许你指定数组的类型,并且可以避免类型转换的开销。

String[] array=list.toArray(new String[0]);

String[] array=list.toArray(value->new String[value]);

String[] array=list.toArray(String[]::new);
索引

索引就是0,1,2,… 用于标识数组或集合中元素的位置

List 接口通过索引(index)访问元素,使用 get(int index) 方法可以获取指定索引位置的元素。

String s=list.get(0);

Collection集合中三种常见的遍历方式

迭代器遍历

获取集合的迭代器对象,对迭代器对象使用.next()方法

List<String> names=new ArrayList<>();
Iterator<String> it=names.iterator();
//获取当前索引值下的`对象`,并向下移动一个索引
names.next();
//集合中是否还含有下一个对象
names.hasNext();

下面的增强 for 循环和 forEach 循环,它们在内部都是通过迭代器对象来实现的,但隐藏了迭代器的实现细节。

增强for循环

image-20250306234458607

  • 增强for可以用来遍历集合或者数组

    对于数组,编译器会将增强 for 循环转换为普通的 for 循环

    对于集合,编译器会将增强 for 循环转换为使用迭代器的代码。

  • 增强for遍历集合,本质就是迭代器遍历集合的简化写法

// 增强for遍历数组
String[] users={"张三","李四","王五"};
for(String user:users){
	System.out.println(user)
}
forEach循环

forEach 方法接受一个 Consumer 函数式接口的实现,这个实现可以是一个 Lambda 表达式、匿名内部类、方法引用或具体的实现类实例。通常使用Lambda 表达式

List<String> names=new ArrayList<>();
names.add("张三");
names.add("李四");
names.add("王五");
// [张三, 李四, 王五]
// 使用lambda表达式
names.forEach((s)->System.out.println(s));
// 使用方法引用
names.forEach(System.out::println);

遍历List中的并发修改异常(ConcurrentModificationException)

问题引入
List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(2);
        list.add(3);
		list.add(4);

		for(int i=0;i<list.size();i++){
    		if (list.get(i) % 2 == 0) { // 删除偶数
                list.remove(i);
            }
		}
		    // 预期结果[1,2,2,3,4]
            // 实际结果是[1,2,3]

        for (Integer i:list) {
            if (list.get(i) % 2 == 0) { // 删除偶数
                list.remove(i);
            }
        }
            // 使用增强for循环直接报ConcurrentModificationException异常

ConcurrentModificationException异常

image-20250313131444460

解决方法

① 如果集合支持索引,可以使用for循环遍历,每删除数据后做i--;或者可以倒着遍历

② 可以使用迭代器遍历,并用迭代器提供的删除方法

注意:增强for循环/forEach循环均不能解决并发修改异常问题,因此它们只适合做数据的遍历,不适合同时做增删操作。

for循环 i–

写累了,承受了这个年纪不该承受的(惆怅脸)…

for(int i=0;i<list.size();i++){
    		if (list.get(i) % 2 == 0) { // 删除偶数
                list.remove(i);
                i--;
            }
		}
for循环 倒序遍历
for(int i=list.size()-1;i>-1;i--){
    		if (list.get(i) % 2 == 0) { // 删除偶数
                list.remove(i);
            }
		}
迭代器遍历

使用Iterator的remove方法

Iterator<String> it=list.iterator();
while(it.hasNext()){
	String name=it.next();
	if(name % 2 == 0){
		it.remove();
	}
}

List集合

List集合特有的方法

List集合因为支持索引,所以多了很多与索引相关的方法,当然,Collection的功能List也都继承了。

add、remove、set、get

image-20250309235325320

List<String> names=new ArrayList<>();
names.add("张三");
names.add("李四");
names.add("王五");
// [张三, 李四, 王五]

names.add(2,"赵六");
// [张三, 李四, 赵六, 王五]

names.remove(1);
// 返回李四
// [张三, 王五]

names.set(2,"孙七");
// 返回王五
// [张三, 李四, 孙七]

names.get(0);
//返回张三

ArrayList底层原理

ArrayList底层是基于数组实现的

ArrayList初始化源码

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private Object[] grow(int minCapacity){
	int oldCapacity=elementData.length;
    // ArrayList扩容,每次扩容为原来的50%
	if(oldCapacity>0||elementData!=DEFAULTCAPACITY_EMPTY_ELEMENTDATA){
		int newCapacity=ArraysSupport.newLength(oldCapacity,
		minCapacity-oldCapacity,
		oldCapacity>>1);
		return elementData=Arrays.copyOf(elementData,newCapacity);
	}else{
     // ArrayList初始化,首次初始化的最小长度为10
		return elementData=new Object[Math.max(DAFAULT_CAPACITY,minCapacity)];
	}
}

累了,解释自行ai…

承受了这个年纪不该承受的(惆怅脸)…


LinkedList集合的底层原理

1.LinkedList集合的底层是基于什么实现的?有什么特点?

  • 基于双链表实现的
  • 增删相对快,查询慢,首位操作比较快

image-20250310141428011

基于双链表的这种特点,LinkedList新增了很多首位操作的特有方法。

image-20250310141410787

LinkedList的应用场景
队列

队列 先进先出,后进后出

LinkedList<String> queue=new LinkedList<>();
// 入队
queue.addLast("张三");
queue.addLast("李四");
queue.addLast("王五");
// [张三, 李四, 王五]

//出队
queue.removeFirst();

先进后出,后进先出

// 不要使用多态创建LinkedList<>,否则会使用不了LinkedList独有的方法。
LinkedList<String> stack=new LinkedList<>();

stack.push("第1颗子弹");

stack.push("第2颗子弹");

stack.push("第3颗子弹");

stack.push("第4颗子弹");

System.out.println(stack);

//出栈
stack.pop();

pop就是removeFirst方法的套皮,push是addFirst方法的套皮。

public void push(E e){
	addFirst(e);
}
public E pop(){
	return removeFirst();
}


http://www.kler.cn/a/590406.html

相关文章:

  • QT:动态属性和对象树
  • Compose笔记(九)--Checkbox
  • [数据结构]排序之 快速排序详解(递归版非递归版)
  • 游戏引擎学习第162天
  • 2025年高职大数据可视化实训室建设及实训平台整体解决方案
  • Vue秘籍:如何动态修改页面 Title(浏览器页签名称)?
  • idea cpu干到100%的解决方法?
  • HarmonyOS NEXT开发实战——HUAWEI DevEco Studio 开发指南
  • 车载以太网测试-13【网络层-IGMP协议】
  • 【Godot】Viewpoint
  • mapbox基础,使用线类型geojson加载symbol符号图层,用于标注文字
  • 解锁智慧养老新可能,全面提升养老生活质量
  • Go语言中的错误处理与异常恢复:性能对比与实践思考
  • 【leetcode】51.N皇后
  • 如何检查CMS建站系统的插件是否安全?
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(60)五火七禽扇灭火 - 接雨水(双指针与动态规划)
  • Kubernetes Network Policy使用场景
  • 微软远程桌面即将下架?Splashtop:更稳、更快、更安全的 RDP 替代方案
  • Django 5实用指南(十四)项目部署与性能优化【完】
  • 调用华为云API实现口罩识别