【Lambda】集合的Lambda表达式

news2024/11/28 8:39:43

【Lambda】集合的Lambda表达式

  • 【一】Stream的方法介绍
    • 【1】Stream里常用的方法
    • 【2】collect(toList()) & filter
    • 【3】map
    • 【4】flatMap
    • 【5】max&min
    • 【6】reduce
  • 【二】常用案例总结
    • 【1】准备方法查询数据库获取List结果
    • 【2】取值
    • 【3】分组
    • 【4】去重
    • 【5】排序
    • 【6】list的最值、平均值、求和
    • 【7】List集合求和
    • 【8】过滤
    • 【9】map遍历
    • 【10】map转list,list转map
    • 【11】list和字符串之间的转换
  • 【三】其他案例分析

【一】Stream的方法介绍

【1】Stream里常用的方法

(1)collect(toList()):通过 Stream 生成一个列表
(2)map:将流中的一个值转换成一个新的值
(3)filter:过滤 Stream 中的元素
(4)flatMap:将多个 Stream 连接成一个 Stream
(5)max:求最大值
(6)min:求最小值
(7)reduce:从一组值中生成一个新的值

【2】collect(toList()) & filter

collect(toList()) 的作用是通过一个 Stream 对象生成 List 对象,案例:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().filter((value) -> value > 2).collect(toList());
result.forEach((value) -> System.out.print(value));

上面的代码先创建了一个 List 对象并初始化,然后筛选出大于 2 的值,输出。
filter 方法的作用是过滤 Stream 中的元素,filter 方法是一个高阶函数,接收一个函数接口作为参数,此高阶函数返回一个 boolean 值,返回 true 的元素会保留下来;
collect(toList()) 方法将 filter 操作返回的 Stream 生成一个 List。

【3】map

map 函数的作用是将流中的一个值转换成一个新的值,举个例子,我们要将一个 List 转换成 List ,那么就可以使用 map 方法,示例代码:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<String> result = list.stream().map(value -> String.format("String:%s", value)).collect(toList());
result.forEach(System.out::print);

map 方法将 Integer 元素转换成 String 并使用 collect(toList()) 方法生成一个新的 List。

System.out::print 是 (value) -> System.out.print(value) 的简化版写法。

【4】flatMap

flatMap:将多个 Stream 连接成一个 Stream,这个怎么理解呢,举个栗子:
首先定义一个 List 对象,将这个对象中的每一个 String 都分割成一个字母并生成一个新的 List 对象,代码:

List<String> list = Arrays.asList("abc", "def", "ghi");
List<Character> result = list.stream().flatMap(value -> {
    char[] chars = value.toCharArray();
    Character[] characters = new Character[chars.length];
    for(int i = 0; i < characters.length; i++){
        characters[i] = chars[i];
    }
    return Stream.of(characters);
}).collect(toList());
result.forEach(System.out::println);

上面代码先遍历 list ,通过 flatMap 函数将每个 String 元素都生成一个新的 Stream 并将这些 Stream 连接成一个新的 Stream。

【5】max&min

求最大值最小值

List<Integer> list = Arrays.asList(0, 1, 2, 3);
Comparator<Integer> comparator = (o1, o2) -> o1.compareTo(o2);
System.out.println(list.stream().min(comparator).get());
System.out.println(list.stream().max(comparator).get());

min 和 max 函数需要一个 Comparator 对象为参数作为比对依据。

【6】reduce

从一组值中生成一个新的值,reduce 函数其实用途非常广泛,作用也比较大,我们举一个累加的例子:

List<Integer> list = Arrays.asList(0, 1, 2, 3);
int count = list.stream().reduce(0, (acc, item) -> acc + item).intValue();
System.out.println(count);

reduce 函数的一个参数为循环的初始值,这里计算累加时初始值为 0,acc 代表已经计算的结果,item 表示循环的每个元素。

【二】常用案例总结

【1】准备方法查询数据库获取List结果

用的是Mybatis-plus的mapper,也可以自己自定义一个List集合

@SpringBootTest
public class LambdaTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void selectList() {
        // 通过条件构造器查询一个List集合,如果没有条件,就可以设置null为参数
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }
}

实体类代码为

@Data // 包含以上,除了有参构造
@TableName("user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

输出的结果如下
在这里插入图片描述

【2】取值

从list的实体类中取出某一个目标值,放进新的list结果中。例如,从List集合的User实体类中取出name,并且放进List里。

代码如下(下面这两种写法都可以的!):

List<String> nameList = list.stream().map(User::getName).collect(Collectors.toList());
List<String> nameList = list.stream().map(it->it.getName()).collect(Collectors.toList());

执行的效果如下:
在这里插入图片描述
在这里插入图片描述

【3】分组

把List里的实体类,按照实体类中的某个值进行分类存放,结果使用Map接收。例如我们把List中的User按照年龄进行分类存放到不同的List里。

代码如下:

Map<Integer, List<User>> ageMap = list.stream().collect(Collectors.groupingBy(User::getAge));
ageMap.forEach((k,v)->{
    System.out.println(k+":\n"+String.join("\n",v.toString()));
});

执行的结果如下:
在这里插入图片描述

【4】去重

代码如下:

@Test
public void distinctTield() {
    List<String> numList = Arrays.asList("1","2","2","3","3","4","4","5","6","7","8");
    List<User> userList = userMapper.selectList(null);

    System.out.println(LambdaTest.distinctElements(numList));
    System.out.println(LambdaTest.getNoDuplicateElements(numList));
    System.out.println(LambdaTest.getDuplicateElements(numList));
    System.out.println(LambdaTest.getDuplicateElementsForObject(userList));
    System.out.println(LambdaTest.getNoDuplicateElementsForObject(userList));
    System.out.println(LambdaTest.getElementsAfterDuplicate(userList));
    System.out.println(LambdaTest.getDuplicateObject(userList));
    System.out.println(LambdaTest.getNoDuplicateObject(userList));
    System.out.println(LambdaTest.distinctObject(userList));
}

//(1)把重复的数据删除,只留下一个
//去重后的集合 [1, 2, 3, 4, 5, 6, 7, 8]
public static <T> List<T> distinctElements(List<T> list) {
    return list.stream().distinct().collect(Collectors.toList());
}

//(2)把所有出现重复的数据都删除
//lambda表达式 去除集合重复的值  [1, 5, 6, 7, 8]
public static <T> List<T> getNoDuplicateElements(List<T> list) {
    // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
    Map<T, Long> map = list.stream().collect(Collectors.groupingBy(p -> p,Collectors.counting()));
    System.out.println("getDuplicateElements2: "+map);
    return map.entrySet().stream() // Set<Entry>转换为Stream<Entry>
            .filter(entry -> entry.getValue() == 1) // 过滤出元素出现次数等于 1 的 entry
            .map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
            .collect(Collectors.toList()); // 转化为 List
}

//(3)把出现重复的数据查出来
//lambda表达式 查找出重复的集合 [2, 3, 4]
public static <T> List<T> getDuplicateElements(List<T> list) {
    return list.stream().collect(Collectors.collectingAndThen(Collectors
            .groupingBy(p -> p, Collectors.counting()), map->{
        map.values().removeIf(size -> size ==1); // >1 查找不重复的集合;== 1 查找重复的集合
        List<T> tempList = new ArrayList<>(map.keySet());
        return tempList;
    }));
}

//利用set集合
public static <T> Set<T> getDuplicateElements2(List<T> list) {
    Set<T> set = new HashSet<>();
    Set<T> exist = new HashSet<>();
    for (T s : list) {
        if (set.contains(s)) {
            exist.add(s);
        } else {
            set.add(s);
        }
    }
    return exist;
}

/**-----------对象List做处理--------------*/

//查找对象中某个原属重复的  属性集合
public static List<String> getDuplicateElementsForObject(List<User> list) {
    return list.stream().collect(Collectors.groupingBy(p -> p.getName(),Collectors.counting())).entrySet().stream()// 根据name分类,并且统计每个name出现的次数
            .filter(entry -> entry.getValue() > 1) // >1 查找重复的集合;== 查找不重复的集合
            .map(entry -> entry.getKey())
            .collect(Collectors.toList());
}

//查找对象中某个原属未重复的  属性集合
public static List<String> getNoDuplicateElementsForObject(List<User> list){
    Map<String,List<User>> map = list.stream().collect(Collectors.groupingBy(User::getName));
    return map.entrySet().stream().filter(entry -> entry.getValue().size() == 1)
            .map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
            .collect(Collectors.toList()); // 转化为 List

}

//查找对象中某个原属去重后的集合
public static List<String> getElementsAfterDuplicate(List<User> list) {
    return list.stream().map(o->o.getName()).distinct().collect(Collectors.toList());
}

//对象中某个原属重复的 对象集合
public static List<List<User>> getDuplicateObject(List<User> list) {
    return list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
            .filter(entry -> entry.getValue().size() > 1) // >1 查找重复的集合;== 查找不重复的集合
            .map(entry -> entry.getValue())
            .collect(Collectors.toList());
}

//对象中某个原属未重复 对象集合
public static List<User> getNoDuplicateObject(List<User> list) {
    List<User> cities = new ArrayList<>();
    list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
            .filter(entry -> entry.getValue().size() ==1) //>1 查找重复的集合;== 查找不重复的集合;
            .map(entry -> entry.getValue())
            .forEach(p -> cities.addAll(p));
    return cities;
}


//根据对象的某个原属去重后的 对象集合
public static List<User> distinctObject(List<User> list) {
    return list.stream().filter(distinctByKey(User::getName)).collect(Collectors.toList());
}

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
}

【5】排序

代码如下:

@Test
public void sortField() {
    List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
    List<User> userList = userMapper.selectList(null);

    System.out.println(sort(list));
    System.out.println(reversed(list));
    System.out.println(sortForObject(userList));
    System.out.println(reversedForObject(userList));
    System.out.println(sortForObject2(userList));
}

//list排序 正序
public static <T> List<T> sort(List<T> list){
    return list.stream().sorted().collect(Collectors.toList());
}

//list排序 倒序
public static List<Integer> reversed(List<Integer> list){
    return list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
}

//根据对象某个属性排序  正序
public static List<User> sortForObject(List<User> list){
    return list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
}

//根据对象某个属性排序  倒序
public static List<User> reversedForObject(List<User> list){
    return list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
}

//根据对象两个属性排序  正序
public static List<User> sortForObject2(List<User> list){
    return list.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getId)).collect(Collectors.toList());
}

执行效果如下:
在这里插入图片描述

【6】list的最值、平均值、求和

代码如下:

@Test
public void getInfo() {
    List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
    List<User> userList = userMapper.selectList(null);
    calculation1(list);
    calculation2(userList);
}

//根据对象某个属性求各自值
///IntSummaryStatistics{count=4, sum=132, min=11, average=33.000000, max=55}
public static IntSummaryStatistics calculation1(List<Integer> list){
    IntSummaryStatistics stat = list.stream().collect(Collectors.summarizingInt(p -> p));
    System.out.println("max:"+stat.getMax());
    System.out.println("min:"+stat.getMin());
    System.out.println("sum:"+stat.getSum());
    System.out.println("count:"+stat.getCount());
    System.out.println("average:"+stat.getAverage());
    Integer max = list.stream().reduce(Integer::max).get();//得到最大值
    Integer min = list.stream().reduce(Integer::min).get();//得到最小值
    System.out.println("max:"+max+";min:"+min);
    return stat;
}
//根据对象某个属性求各自值
// sum=397,max=29,min=12,ave=23.352941176470587
public static void calculation2(List<User> list){
    System.out.println("sum="+ list.stream().mapToInt(User::getAge).sum());
    System.out.println("max="+ list.stream().mapToInt(User::getAge).max().getAsInt());
    System.out.println("min="+ list.stream().mapToInt(User::getAge).min().getAsInt());
    System.out.println("ave="+ list.stream().mapToInt(User::getAge).average().getAsDouble());
}

代码运行效果如下:
在这里插入图片描述

【7】List集合求和

public static void main(String[] args) {
    List<BigDecimal> list = new ArrayList<>();
    list.add(BigDecimal.valueOf(1.1));
    list.add(BigDecimal.valueOf(1.2));
    list.add(BigDecimal.valueOf(1.3));
    list.add(BigDecimal.valueOf(1.4));

    BigDecimal decimal = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
    System.out.println(decimal);
}

【8】过滤

//功能描述 过滤
public static List<City> filter(List<City> list){
    return list.stream().filter(a -> a.getTotal()>44).collect(Collectors.toList());
}

【9】map遍历

(1)stream遍历key和value

map.forEach((k, v) -> System.out.println("key:value = " + k + ":" + v));

【10】map转list,list转map

(1)map和list的互相转换

//功能描述 List转map
public static void listToMap(List<User> list){
    //用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
    Map<String,User> map = list.stream().collect(Collectors.toMap(User::getName,user -> user, (k1, k2) -> k1));
    map.forEach((k,v) -> System.out.println("k=" + k + ",v=" + v));
}

//功能描述 map转list
public static void mapToList(Map<String,User> map){
    List<User> list =
            map.entrySet().stream().map(key -> key.getValue()).collect(Collectors.toList());
    System.out.println(list);
    list.forEach(bean -> System.out.println(bean.getName() + "," + bean.getEmail()));
}

(2)map转list

map.entrySet().stream().map(e -> new Person(e.getKey(),e.getValue())).collect(Collectors.toList());
map.keySet().stream().collect(Collectors.toList());
map.values().stream().collect(Collectors.toList());

(3)list转map

Map<Integer, String> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getId, Hosting::getName));

Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId,Function.identity()));

//看来还是使用JDK 1.8方便一些。另外,转换成map的时候,可能出现key一样的情况,如果不指定一个覆盖规则,上面的代码是会报错的。转成map的时候,最好使用下面的方式
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));

【11】list和字符串之间的转换

//功能描述 字符串转list
public static void stringToList(String str){
    //不需要处理
    //<String> list = Arrays.asList(str.split(","));
    //需要处理
    List<String> list = Arrays.asList(str.split(",")).stream().map(string -> String.valueOf(string)).collect(Collectors.toList());
    list.forEach(string -> System.out.println(string));
}

//功能描述 姓名以逗号拼接
public static void joinStringValueByList(List<User> list){
    System.out.println(list.stream().map(User::getName).collect(Collectors.joining(",")));
}

//功能描述 姓名以逗号拼接
public static void joinStringValueByList2(List<String> list){
    //方式一
    System.out.println(String.join(",", list));
    //方式二
    System.out.println(list.stream().collect(Collectors.joining(",")));
}

【三】其他案例分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/524480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp制作水印相机给图片添加水印并且保存图片至本地

uniapp保存文件的三种方式 文件主要分为两大类&#xff1a; 1.代码包文件&#xff1a;代码包文件指的是在项目目录中添加的文件。 2.本地文件&#xff1a;通过调用接口本地产生&#xff0c;或通过网络下载下来&#xff0c;存储到本地的文件。 其中本地文件又分为三种&#…

【K8s】Service详解

文章目录 一、Service介绍1、认识Service2、kube-proxy的三种工作模式3、Service的类型 二、Service的使用1、实验数据准备2、Service类型为ClusterIP补充&#xff1a;Endpoints补充&#xff1a;负载分发策略 3、Service类型为HeadLiness3、Service类型为NodePort4、Service的类…

Ovito渲染技巧之体系边界识别

关注 M r . m a t e r i a l , \color{Violet} \rm Mr.material\ , Mr.material , 更 \color{red}{更} 更 多 \color{blue}{多} 多 精 \color{orange}{精} 精 彩 \color{green}{彩} 彩&#xff01; 主要专栏内容包括&#xff1a; †《LAMMPS小技巧》&#xff1a; ‾ \textbf…

性能、性能还是性能---下一代Android性能框架分析

性能优化的重要性和难度毋庸置疑&#xff0c;事实上&#xff0c;性能优化也是一个永无止境的游戏&#xff0c;总会发现有一些东西需要优化。但是不可避免的是&#xff0c;这也是一个边际效益递减的事情&#xff0c;项目或应用获得的收益在一定程度上也会逐渐降低。What’s new …

ReentrantLock 原理

目录 ReentrantLock 概述 ReentrantLock 的原理 什么是 AQS ? 获取锁资源(以⾮公平锁为例) tryAcquire addWaiter acquireQueued 释放锁资源 ⾮公平锁体现在哪⾥&#xff1f; 调试代码 总结 ReentrantLock 概述 ReentrantLock是Lock接⼝的默认实现&#xff0c;是⼀…

【Linux】-关于Linux的指令(下)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树 ❤️‍&#x1fa79;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a8;作者gitee:gitee &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 文章目录 前言一、时间相关的指令二、cal指令三、find -name指…

Centos7 经典模式安装GBase 8s 图文教程

Centos7安装GBase 8s 图文教程 前言1.1 硬件要求1.2 系统要求1.3 虚拟 PC 软件1.4 安装及配置数据库服务器1.4.1 创建 gbasedbt 组和用户1.4.2 创建 GBase 8s 数据库安装目录1.4.3 上传并解压安装包1.4.4 执行安装 参考文献 前言 本篇博文分享如何在Centos7 x86架构的系统中安…

第2章-Selenium-API操作

目标&#xff1a; 1. 熟练应用八种元素定位方式 2. 掌握对元素和浏览器的操作方法 3. 掌握键盘鼠标的操作 4. 掌握元素等待的操作 5. 掌握下拉选择框、 警告框和滚动条的操作 6. 掌握如何切换frame框架和多窗口 7. 掌握如何实现窗口截图 1.元素定位 1. 掌握id、 name、 cla…

【leetcode】622 二叉树的最大宽度

题目描述 给你一棵二叉树的根节点 root &#xff0c;返回树的 最大宽度 。 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点&#xff08;即&#xff0c;两个端点&#xff09;之间的长度。将这个二叉树视作与满二叉树结构相同&#…

MATLAB 之 M 文件和程序控制结构(顺序、选择、循环)

文章目录 一、M 文件1. M 文件的建立与打开1.1 建立新的 M 文件1.2 打开已有的 M 文件 2. M 文件的分类 二、 程序控制之顺序结构1. 数据的输入2. 数据的输出3. 程序的暂停 三、程序控制之选择结构1. if 语句2. switch 语句3. try 语句 四、程序控制之循环结构1. for 语句2. wh…

畸变像差校正技术(畸变相位补偿)发展现状及其仿真实验研究-技术汇总-Matlab代码

▒▒本文目录▒▒ 一、引言二、物理方法2.1 基于二次曝光法的畸变像差补偿仿真实验验证 三、数值方法3.1 基于主成分分析法的畸变像差补偿仿真实验验证3.2 基于标准多项式拟合法的畸变像差校正仿真实验验证3.3 基于最小二乘拟合法的畸变像差校正仿真实验验证3.4 基于泽尼克多项…

Simulink 自动代码生成电机控制——永磁同步电机参数获取

目录 前言 极对数测量 电阻测量&#xff08;Rs&#xff09; 电感测量&#xff08;Ld和Lq&#xff09; 磁链测量 总结 前言 在建模之前或者需要更换一个新电机&#xff0c;需要获取目标电机的电气参数&#xff0c;如果参数不对&#xff0c;对于电流环参数的整定&#xff0…

2023/05/08~14 刷题记录

A - Plus and Multiply 题意&#xff1a; 题解&#xff1a; 题目说可以将集合里面的数字 *a 或者 b 操作&#xff0c;并将新的值放进集合中&#xff0c;首先想到 dfs 暴力求解&#xff0c;但是太暴力了&#xff0c;直接 时间超限 。通过观察我们可以知道&#xff0c;要求 n 是否…

前端模块化

什么是模块化 事实上模块化开发最终目的是将程序划分成一个个小的结构在这个结构中编写属于自己的逻辑代码&#xff0c;有自己的作用域&#xff0c;不会影响到其他的结构这个结构可以将自己希望暴露的变量、函数、对象等导出给其他结构使用。可以通过某种方式&#xff0c;导入…

电脑软件:国内最好用解压缩软件 7-Zip 新版本发布

5 月 9 日消息&#xff0c;7-Zip 是一款拥有极高压缩比的的开源压缩软件&#xff0c;支持 LZMA2 等 7 种开源算法&#xff0c;以及支持较广泛的压缩格式 .7z&#xff0c;体积不大&#xff08;1.5MB&#xff09;、功能完善&#xff0c;除了默认 UI 不符合国内审美外几乎没什么可…

Oracle数据库安装教程,并实现公网远程连接【内网穿透】

✨ 目录 &#x1f388; 前言&#x1f388; 1. 数据库搭建&#x1f388; 2. 内网穿透&#x1f388; 2.1 安装cpolar内网穿透&#x1f388; 2.2 创建隧道映射 &#x1f388; 3. 公网远程访问&#x1f388; 4. 配置固定TCP端口地址&#x1f388; 4.1 保留一个固定的公网TCP端口地址…

Java经典笔试题—day08

Java经典笔试题—day08 &#x1f50e;选择题&#x1f50e;编程题&#x1f95d;两种排序方法&#x1f95d;求最小公倍数 &#x1f50e;结尾 &#x1f50e;选择题 (1)下列选项中关于Java中super关键字的说法正确的是&#xff08;&#xff09; A.super关键字是在子类对象内部指代…

JAVA JDK下载安装手册

JDK的介绍与安装 JDK简介 JDK是 Java 语言的软件开发工具包&#xff0c;主要用于移动设备、嵌入式设备上的java应用程序。编写 Java 程序必须使用 JDK&#xff0c;它提供了编译和运行 Java 程序的环境。是整个java开发的核心。 准备JDK 本次使用的是JDK1.8 如下所示: 下载完…

记两道AES-CBC题

文章目录 知识导入&#xff08;AES-CBC模式&#xff09;题一(buu [ACTF新生赛2020]crypto-aes 1)题目描述&#xff1a;题目分析&#xff1a;知识导入os.urandom(n)函数比特&#xff0c;字节&#xff0c;二进制数之间的关系AES.new(key,AES.MODE_CBC,iv) 题二(crack AES-CBC IV)…

小黑子—Java从入门到入土过程:第九章-IO流

Java零基础入门9.0 Java系列第九章- IO流1. 初识IO流2. IO流的体系2.1 字节流2.1.1 FileOutputStream 字符串输出流2.1.1 - I 字符串输出流的细节2.1.1 - II FileOutputStream写数据的3种方式2.1.1 -III FileOutputStream写数据的两个小问题 2.1.2 FileInputStream 字符串输入流…