sublist详解

本文详细解析了ArrayList的subList方法,包括其返回的子列表特性,如视图关系、非结构性修改与结构性修改的影响。通过示例展示了在修改父列表时可能导致的ConcurrentModificationException异常。此外,还提到了强转子列表为ArrayList时可能抛出的ClassCastException异常,强调了正确使用subList的方法和注意事项。

接口中定义

List<E> subList(int fromIndex, int toIndex);

1,该方法返回的是父list的一个视图,从fromIndex(包含),到toIndex(不包含)。fromIndex=toIndex 表示子list为空

2,父子list做的非结构性修改(non-structural changes)都会影响到彼此:所谓的“非结构性修改”,是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。

3,对于结构性修改,子list的所有操作都会反映到父list上。但父list的修改将会导致返回的子list失效。

4,tips:如何删除list中的某段数据:

注意:
ArrayList的subList结果不可强转成ArrayList,否则会抛出 ClassCastException 异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.说明:subList 返回的是 ArrayList 的内部类 SubList,并不是ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。

在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

 public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        arrayList.add(6);
        arrayList.add(7);

        List<Integer> list = arrayList.subList(1, 3);

        for (Integer integer : list) {
            System.out.println(" "+integer);
        }

        System.out.println(" modify arrayList");
        arrayList.remove(0);

        for (Integer integer : list) {
            System.out.println(" "+integer);
        }
    }


运行结果如下
在这里插入图片描述
ArrayList中有个protected transient int modCount = 0;
用来记录当前ArrayList被修改的次数。比如add(),remove()等都会导致modeCount增加:

ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount同步ArrayList中的modeCount:

SubList对象每次再遍历时,会将自己的modeCount与ArrayList的modeCount进行对比,如果两个值不一样就会报异常:ConcurrentModificationException

<think>嗯,用户想了解flatMap的详细用法和使用示例。首先我需要回忆一下flatMap的基本概念。flatMap通常在函数式编程和流处理中使用,比如在Java的Stream API或者RxJava里。它的作用是将每个元素转换成一个流,然后把所有流连接起来成为一个新的流。这样可以将嵌套结构展平。 接下来,我应该从基础开始解释,先讲map和flatMap的区别,这样用户能更好理解。比如,map是一对一的转换,而flatMap是一对多的转换,并且会合并结果。需要举一些例子来说明,比如处理嵌套数组或者拆分字符串。 然后,要给出不同编程语言中的示例,比如JavaScript、Java和Python,因为用户可能使用不同的语言环境。在JavaScript中,数组的flatMap方法可以直接使用;Java的Stream API需要结合例子;Python可能需要用列表推导式或者其他方法模拟。 还要注意用户提到的引用内容,虽然引用里的例子是关于数组展平和处理空值的,但用户可能需要更全面的示例,包括不同场景的应用。比如,处理包含多个元素的列表,或者异步操作中的flatMap用法,比如RxJava。 另外,用户可能想知道flatMap的原理,比如它如何将多个流合并。这部分需要简单解释,避免过于深入底层实现,但要让用户明白它是如何工作的。 最后,生成相关问题的时候,要考虑到用户可能进一步想知道flatMap与map的区别、性能优化、应用场景以及在不同语言中的实现。这些问题应该能帮助用户深化理解,并解决他们可能遇到的后续问题。 需要检查语法是否正确,尤其是LaTeX格式的部分,比如变量和代码块是否正确标注。同时,确保回答结构清晰,分点说明,让用户容易跟随。还要注意引用标识的正确添加,虽然用户提供的引用可能不完全相关,但需要适当提及。</think>### flatMap 详解与示例 #### 一、基础概念 flatMap 是函数式编程中常见的操作符,核心功能是通过 **映射+展平** 处理嵌套结构数据。与 map 的区别在于: - $map$:1对1转换元素,例如 `[1,2].map(x => x*2)` → `[2,4]` - $flatMap$:1对多转换后自动展平,例如 `[1,2].flatMap(x => [x, x*10])` → `[1,10,2,20]` #### 二、使用场景 1. **嵌套数组展平** ```javascript const arr = [[1,2], [3,4]]; arr.flatMap(subArr => subArr); // [1,2,3,4] ``` 2. **数据拆分与转换** ```java List<String> words = Arrays.asList("Hello World", "Java Stream"); words.stream() .flatMap(str -> Arrays.stream(str.split(" "))) // 拆分为单词流 .forEach(System.out::println); // 输出: Hello World Java Stream ``` 3. **异步流处理(RxJava)** ```java Observable.just("user1", "user2") .flatMap(id -> fetchUserDetails(id)) // 将每个ID转换为异步请求流 .subscribe(user -> System.out.println(user)); ``` #### 三、实现原理 1. **执行步骤** - Step 1:对每个元素执行映射函数生成新流 - Step 2:将所有流合并为单一输出流 $$ \text{flatMap}(f)(S) = \bigcup_{x \in S} f(x) $$ 2. **与 map 的对比** | 操作符 | 输入类型 | 输出类型 | |--------|---------|---------| | map | T | R | | flatMap| T | Stream<R>| #### 四、跨语言示例 1. **Python(通过生成器模拟)** ```python data = ["a,b", "c,d"] result = [item for sublist in (s.split(',') for s in data) for item in sublist] # ['a','b','c','d'] ``` 2. **JavaScript 进阶用法** ```javascript // 过滤并转换数据 [1,2,3].flatMap(x => x%2 === 0 ? [] : [x*10]); // 输出:[10, 30] ``` #### 五、注意事项 1. **性能影响**:在 Java Stream 中频繁创建流对象可能降低性能[^2] 2. **顺序保留**:多数实现保证元素顺序(如 Java Stream、RxJava) 3. **空值处理**:`flatMap(() => null)` 可能导致异常,建议返回空流
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值