文章目录
- 十五、Stream流、File、方法递归
- 1、Stream
- 1.1 什么是Stream
- 1.2 获取Stream流
- 1.3 Stream流常见的中间方法
- 1.3 Stream流常见的终结方法
- 1.4 收集Stream流
- 2、File、IO流(一)
- 2.1 存储数据的方案
- 2.2 File:代表文本
- 2.3 常用方法一:判断文件路径、获取文件信息
- 2.4 常用方法二:创建文件、删除文件
- 2.5 常用方法三:遍历文件夹
- 2.6 前置知识:方法递归
- 2.6.1 认识递归的形式
- 2.6.2 应用、执行流程、算法思想
- 2.6.3 其他应用:文件搜索
- 3、字符集
- 3.1 常见字节码介绍
- 3.2 字符集的编码、解码操作
十五、Stream流、File、方法递归
1、Stream
1.1 什么是Stream
也叫Stream流,是JDK8开始新增的一套API,可以用于操作集合或者数组中的数据
优势:Stream流集合了Lambda的语法风格来编程,提供了一种更加强大、更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好
package com.tender.d1_stream;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;public class StreamTest1 {public static void main(String[] args) {// 目标:体验Stream流的使用List<String> list = new ArrayList<>();list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");// 1、拿出姓张的放到新集合中去。List<String> newList = new ArrayList<>();for (String s : list) {if(s.startsWith("张")) {newList.add(s);}}System.out.println(newList);// 2、体验Stream流List<String> list1 = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());System.out.println(list1);}
}
1.2 获取Stream流
package com.tender.d1_stream;import java.util.*;
import java.util.stream.Stream;/****/
public class StreamTest2 {public static void main(String[] args) {// 目标:获取Stream流。// 1、获取集合的Stream流: default Stream<E> stream()Collection<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若","赵敏","张强","张三丰");Stream<String> listS = list.stream();// 2、获取Map集合的Stream流Map<String,Integer> map = new HashMap<>();// a、获取键流Stream<String> keyS = map.keySet().stream();// b、获取值流Stream<Integer> valueS = map.values().stream();// c、获取键值对流.Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();// 3、获取数组的StreamString[] names = {"赵敏", "王菲", "小昭"};Stream<String> stream1 = Arrays.stream(names);Stream<String> stream2 = Stream.of(names);}
}
1.3 Stream流常见的中间方法
中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)
package com.tender.d1_stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;public class StreamTest3 {public static void main(String[] args) {// 目标:掌握Stream流的常见方法。List<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若","赵敏","张强","张三丰");// 1、过滤方法list.stream().filter(s -> s.startsWith("张") ).forEach(s -> System.out.println(s));// 2、准备一个集合,排序。List<Movie> movies = new ArrayList<>();movies.add(new Movie("摔跤吧,爸爸", 9.5, "阿米尔汗"));movies.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies.add(new Movie("阿甘正传", 7.5, "汤姆汉克斯"));// 集合中如果存储对象,方式一:对象类可以实现Comparable接口,指定比较规则// sorted方法就可以按照规则进行排序,否则报错!movies.stream().sorted().forEach(s -> System.out.println(s));System.out.println("-----------------------------------------------");movies.stream().sorted((m1, m2) -> Double.compare(m2.getScore(), m1.getScore())).forEach(System.out::println);// 3、limit取前几个System.out.println("-----------------------------------------------");movies.stream().sorted((m1, m2) -> Double.compare(m2.getScore(), m1.getScore())).limit(2).forEach(System.out::println);// 4、跳过前几个skipSystem.out.println("-----------------------------------------------");movies.stream().sorted((m1, m2) -> Double.compare(m2.getScore(), m1.getScore())).skip(2).forEach(System.out::println);// 5、distinct去重复System.out.println("-----------------------------------------------");// 去重复:需要重写对象类的hashCode和equals方法movies.stream().sorted((m1, m2) -> Double.compare(m2.getScore(), m1.getScore())).distinct().forEach(System.out::println);// 6、map加工方法:把流上的数据加工成新数据。System.out.println("-----------------------------------------------");movies.stream().map(m -> {m.setScore(m.getScore() + 2);return m;}).forEach(System.out::println);// 7、合并流。// 把两个流接起来 。Stream<String> s1 = Stream.of("张三", "楚留香", "西门吹牛");Stream<String> s2 = Stream.of("李四", "石观音");Stream<String> allStream = Stream.concat(s1, s2);long count = allStream.count(); // count:统计个数System.out.println(count);}
}
1.3 Stream流常见的终结方法
终结方法值得是调用完成后,不回返回新的Stream了,没法继续使用流了。
// 目标:Stream流的常见终结方法。List<Movie> movies = new ArrayList<>();movies.add(new Movie("摔跤吧,爸爸", 9.5, "阿米尔汗"));movies.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies.add(new Movie("阿甘正传", 7.5, "汤姆汉克斯"));// 1、forEachmovies.stream().forEach(System.out::println);// 2、countlong count = movies.stream().skip(2).count();System.out.println(count);// 3、取最大值Movie movie = movies.stream().max((m1, m2) -> Double.compare(m1.getScore(), m2.getScore())).get();System.out.println(movie);Movie movie2 = movies.stream().min((m1, m2) -> Double.compare(m1.getScore(), m2.getScore())).get();System.out.println(movie2);
1.4 收集Stream流
就是把Stream流操作后的结果转回到集合或者数组中去返回
Stream流:方便操作集合/数组的手段;集合/数组:才是开发中的目的。
// 4、收集Stream流:把流中的数据恢复到集合或者数组中去。List<String> list = new ArrayList<>();list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");list.add("张三丰");// 收集到List集合List<String> names = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());System.out.println(names);names.add("张麻子");System.out.println(names);// 收集到Set集合Set<String> names2 = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toSet());System.out.println(names2);names2.add("张麻子");System.out.println(names2);// 收集到数组Object[] names3 = list.stream().filter(s -> s.length() == 3).toArray();System.out.println(Arrays.toString(names3));// 拓展
// String[] names4 = list.stream().filter(s -> s.length() == 3).toArray(String[]::new);
// System.out.println(Arrays.toString(names4));// 收到到Map集合。List<Movie> movies1 = new ArrayList<>();movies1.add(new Movie("摔跤吧,爸爸", 9.5, "阿米尔汗"));movies1.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies1.add(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"));movies1.add(new Movie("阿甘正传", 7.5, "汤姆汉克斯"));Map<String, Double> map = movies1.stream().distinct().collect(Collectors.toMap(m -> m.getName(), m -> m.getScore()));System.out.println(map);
2、File、IO流(一)
2.1 存储数据的方案
2.2 File:代表文本
File是Java.io包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)
File类只能对文件进行操作,不能读写文件里面存储的数据
相对路径:绝对路径是带盘符的
绝对路径:相对路径不带盘符,默认到当前工程文件下找文件
2.3 常用方法一:判断文件路径、获取文件信息
package com.tender.d2_file;import java.io.File;
import java.text.SimpleDateFormat;/**目标:掌握File提供的判断文件类型、获取文件信息功能*/
public class FileTest2 {public static void main(String[] args) {// 1.创建文件对象,指代某个文件// File f1 = new File("E:/resource/meinv.jpg");//File f1 = new File("day08-stream-file-charset\\src\\dlei01.txt");File f1 = new File("day08-stream-file-io\\src\\com\\tender\\d2_file\\gdd.txt");// 2、public boolean exists():判断当前文件对象,对应的文件路径是否存在,存在返回true.System.out.println(f1.exists());// 3、public boolean isFile() : 判断当前文件对象指代的是否是文件,是文件返回true,反之。System.out.println(f1.isFile());// 4、public boolean isDirectory() : 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。System.out.println(f1.isDirectory());// 5.public String getName():获取文件的名称(包含后缀)System.out.println(f1.getName());// 6.public long length():获取文件的大小,返回字节个数System.out.println(f1.length());// 7.public long lastModified():获取文件的最后修改时间。long time = f1.lastModified();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");System.out.println(sdf.format(time));// 8.public String getPath():获取创建文件对象时,使用的路径System.out.println(f1.getPath());// 9.public String getAbsolutePath():获取绝对路径System.out.println(f1.getAbsolutePath());}
}
2.4 常用方法二:创建文件、删除文件
创建文件
删除文件
package com.tender.d2_file;import java.io.File;/*** 目标:掌握File创建和删除文件相关的方法。*/
public class FileTest3 {public static void main(String[] args) throws Exception {// 1、public boolean createNewFile():创建一个新文件(文件内容为空),创建成功返回true,反之。File f1 = new File("D:/studyFile/gdd.txt");System.out.println(f1.createNewFile());// 2、public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹File f2 = new File("D:/studyFile/xxx");System.out.println(f2.mkdir());// 3、public boolean mkdirs()(重点):用于创建文件夹,注意:可以创建多级文件夹File f3 = new File("D:/studyFile/xxx/vvvvv/aaaaaaaa");System.out.println(f3.mkdirs());// 3、public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹。File f4 = new File("D:/studyFile/xxx/vvvvv/aaaaaaaa");System.out.println(f4.delete());}
}
2.5 常用方法三:遍历文件夹
注意事项:
当主调是文件,或者路径不存在时,返回null
当主调时空文件夹时,返回一个长度为0的数组
当主调时一个有内容的文件夹时,将里面所有一级文件和文件夹路径放在File数组中返回
当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
当主调时一个文件夹,但是没有权限访问该文件夹时,返回null
package com.tender.d2_file;import java.io.File;/*** 目标:掌握File提供的遍历文件夹的方法。*/
public class FileTest4 {public static void main(String[] args) {File f = new File("D:\\studyFile");// 1、public String[] list():获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。String[] list = f.list();for (String s : list) {System.out.println(s);}// 2、public File[] listFiles():(重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)File[] files = f.listFiles();for (File file : files) {System.out.println(file.getAbsolutePath());}}
}
2.6 前置知识:方法递归
2.6.1 认识递归的形式
什么是方法递归?
递归式一种算法,在程序设计语言中广泛应用
从形式上说:方法调用自生的形式称为方法递归
递归的形式
直接递归:方法自己调用自己
间接递归:方法调用其他方法,其他方法有回调方法自己
使用方法递归时需要注意的问题:
递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误
package com.tender.d3_recursion;public class RecursionTest1 {public static void main(String[] args) {// 目标:认识递归的形式。test1();}public static void test2(){System.out.println("==test2==");test3();}public static void test3() {System.out.println("==test3==");test2(); // 间接递归:}public static void test1(){System.out.println("==test1==");test1(); // 直接递归:自己调用自己}
}
2.6.2 应用、执行流程、算法思想
导学案例:
计算n的阶乘
package com.tender.d3_recursion;public class RecursionTest2 {public static void main(String[] args) {// 目标:递归的算法基础:解决求阶乘。System.out.println("1-5的阶乘:" + f(5));}public static int f(int n) {if (n == 1) {return 1;} else {return f(n - 1) * n;}}}
递归算法三要素:
递归公式
递归的终结点
递归的方向必须走向终结点
2.6.3 其他应用:文件搜索
package com.tender.d3_recursion;import java.io.File;
import java.io.IOException;public class FileSearchTest5 {public static void main(String[] args) throws IOException {// 目标:文件搜索。File dir = new File("D:/");searchFile(dir, "QQ.exe");}/*** 文件搜索** @param dir 传需要查询的目录* @param fileName 传需要查询的文件名*/public static void searchFile(File dir, String fileName) throws IOException {// 判断文件夹是否为空,是否为文件,是否大小为0if (dir.isFile() || dir.length() == 0 || !dir.exists()) {return;}// 获取到文件对象File[] files = dir.listFiles();if (files == null || files.length == 0) {return;}// 遍历文件夹对象for (File file : files) {if (file.isFile()) {if (file.getName().contains(fileName)) {//是要找的文件System.out.println(file.getAbsolutePath());Runtime r = Runtime.getRuntime();r.exec(file.getAbsolutePath());}} else {// 如果是文件夹,递归调用 searchFile 方法searchFile(file, fileName);}}}
}
3、字符集
3.1 常见字节码介绍
标种ASII字符集
美国信息交换标准代码,包括了英文、符号等
ASII使用1个字节存储一个字符,首尾是0,总共可以表示128个字符集。
GBK(汉字内码扩展规范,国标)
汉字编码字符集,包含了2万多个汉字等字符,GBK中ige中问字符编码成两个字节的形式存储
注意:GBK兼容了ASCII字符集
Unicode字符集(统一码,也叫万国码)
是国际组织制定的,可以容纳世界上所有的文字、符号的字符集。占用存储空间大,通信效率变低
UTF-8
是Unicode字符集的一种编码方案,采取可变张编码方案,共分四个长度区:1个字节、2个字节、3个字节、4个字节
英文字符、数字等只占1个字节(兼容ASCII编码),汉字字符占用3个字节
3.2 字符集的编码、解码操作
编码:把字符按照指定字符集编码成字节
解码:把字节按照指定字符集解码成字符
/*** @author Tender* @date 2025/5/1 17:19*/package com.tender.d4_charset;import java.util.Arrays;public class EncodingDemo {public static void main(String[] args) throws Exception {String code = "niubi我在喝水看美女";byte[] bytes = code.getBytes();System.out.println(Arrays.toString(bytes));String code1 = "niubi我在喝水看美女";byte[] bytes1 = code1.getBytes("GBK");System.out.println(Arrays.toString(bytes1));String s = new String(bytes);System.out.println(s);String s1 = new String(bytes1);System.out.println(s1);}
}