一,JDK8新特性:Stream

1,认识Stream

  • 也叫Stream流,是jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。

  • 优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好。

案例需求:有一个List集合,元素有"河南大学","郑州大学","河南科技大学","黄淮学院","华北水利水电大学","河南工业大学","河南农业大学",找出河南开头,且是6个字的校名,存入到一个新集合中去。

HashSet<String> set = new HashSet<>();
Collections.addAll(set,"河南大学", "郑州大学", "河南科技大学", "黄淮学院", "华北水利水电大学", "河南工业大学", "河南农业大学");

用传统方式来做,代码是这样的

// 找出河南开头,且是6个字的校名,存入到一个新集合中去。
List<String> list = new ArrayList<>();
for (String name : set) {if(name.startsWith("张") && name.length() == 3){list.add(name);}
}
System.out.println(list);

用Stream流来做,代码是这样的(ps: 是不是想流水线一样,一句话就写完了)

List<String> list = set.stream().filter(s -> s.startsWith("河南") && s.length() == 6).collect(Collectors.toList());System.out.println(list);
}

下面我们就把目光定睛在Stream流的获取,对流的处理,以及总结方法。

2,Stream流的创建

主要掌握下面四点:1、如何获取List集合的Stream流?2、如何获取Set集合的Stream流?3、如何获取Map集合的Stream流?4、如何获取数组的Stream流?
// 1、如何获取List集合的Stream流?
List<String> names = new ArrayList<>();
Collections.addAll(names, "张三丰","张无忌","周芷若","赵敏","张强");
Stream<String> stream = names.stream();// 2、如何获取Set集合的Stream流?
Set<String> set = new HashSet<>();
Collections.addAll(set, "刘德华","张曼玉","蜘蛛精","马德","德玛西亚");
Stream<String> stream1 = set.stream();
stream1.filter(s -> s.contains("德")).forEach(s -> System.out.println(s));// 3、如何获取Map集合的Stream流?
Map<String, Double> map = new HashMap<>();
map.put("古力娜扎", 172.3);
map.put("迪丽热巴", 168.3);
map.put("马尔扎哈", 166.3);
map.put("卡尔扎巴", 168.3);Set<String> keys = map.keySet();
Stream<String> ks = keys.stream();Collection<Double> values = map.values();
Stream<Double> vs = values.stream();Set<Map.Entry<String, Double>> entries = map.entrySet();
Stream<Map.Entry<String, Double>> kvs = entries.stream();
kvs.filter(e -> e.getKey().contains("巴")).forEach(e -> System.out.println(e.getKey()+ "-->" + e.getValue()));// 4、如何获取数组的Stream流?
String[] names2 = {"张翠山", "东方不败", "唐大山", "独孤求败"};
Stream<String> s1 = Arrays.stream(names2);
Stream<String> s2 = Stream.of(names2);

总结:Collection接口的实现类都可以通过对象调用stream( ) 方法来获取Stream对象。而对于map这个特殊的集合只能先获取其keys或values的对象,得到一个集合然后在调用其中的Stream对象 。当然也可以通过内部对键值对的封装的Set集合获取Stream对象。
而对于数组可以通过Arrays.stream()方法来获取。

对于不太确定或者已经确定的数据都可以视同Stream类的静态方法 of()来获取对象。很香。类比于Collections的addAll方法。

Stream<String> dx = Stream.of("河南大学", "郑州大学", "河南科技大学", "华北水利水电大学", "河南工业大学");

3,Stream的常用方法

上面学习了Stream流的获取,下面再学习 第二步,Stream流常见的中间方法。

Stream****提供的常用中间方法 说明
Stream filter(Predicate<? super T> predicate) 用于对流中的数据进行过滤。
Stream sorted() 对元素进行升序排序
Stream sorted(Comparator<? super T > comparator) 按照指定规则排序
Stream limit(long maxSize) 获取前几个元素
Stream skip(long n) 跳过前几个元素
Stream distinct() 去除流中重复的元素。
Stream map(Function <? super T ,? extends R> mapper) 对元素进行加工,并返回对应的新流
static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流

通过下面的代码做一个练习:

下面的代码大量的运用lambda,如果没有学,可以看前面的笔记,有详细的介绍。对于lambda表达式中filter方法。可以这样理解其他的也类似。s -> s >= 60 前面代表当前对象,后面的代表的是条件,也就是只有当后面成立的时候(为true)才会将当前的元素,添加到Stream流中。基本都是这种思想

        List<Double> scores = new ArrayList<>();Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0);// 需求1:找出成绩大于等于60分的数据,并升序后,再输出。scores.stream().filter(s -> s >= 60).sorted().forEach(s -> System.out.println(s));List<Student> students = new ArrayList<>();Student s1 = new Student("lucky", 26, 172.5);Student s2 = new Student("Lucy", 26, 172.5);Student s3 = new Student("bob", 23, 167.6);Student s4 = new Student("jack", 25, 169.0);Student s5 = new Student("张一", 35, 183.3);Student s6 = new Student("之辈", 34, 168.5);Collections.addAll(students, s1, s2, s3, s4, s5, s6);// 需求2:找出年龄大于等于23,且年龄小于等于30岁的学生,并按照年龄降序输出.students.stream().filter(s -> s.getAge() >= 23 && s.getAge() <= 30).sorted((o1, o2) -> o2.getAge() - o1.getAge()).forEach(s -> System.out.println(s));// 需求3:取出身高最高的前3名学生,并输出。students.stream().sorted((o1, o2) -> Double.compare(o2.getHeight(), o1.getHeight())).limit(3).forEach(System.out::println);System.out.println("-----------------------------------------------");// 需求4:取出身高倒数的2名学生,并输出。   s1 s2 s3 s4 s5 s6students.stream().sorted((o1, o2) -> Double.compare(o2.getHeight(), o1.getHeight())).skip(students.size() - 2).forEach(System.out::println);// 需求5:找出身高超过168的学生叫什么名字,要求去除重复的名字,再输出。students.stream().filter(s -> s.getHeight() > 168).map(Student::getName).distinct().forEach(System.out::println);// distinct去重复,自定义类型的对象(希望内容一样就认为重复,重写hashCode,equals)students.stream().filter(s -> s.getHeight() > 168).distinct().forEach(System.out::println);Stream<String> st1 = Stream.of("张三", "李四");Stream<String> st2 = Stream.of("张三2", "李四2", "王五");Stream<String> allSt = Stream.concat(st1, st2);allSt.forEach(System.out::println);

还有一个map方法:这个方法用于对值进行操作然后得到返回之后的数据添加到Stream流中的。也很常用

// 需求,将字符串中的数据先切分,然后找出其中的偶数并输出String str = "1,2,3,4,5,6,8,4,6,3,56,3,5,3";String[] split = str.split(",");Stream<String> stream = Stream.of(split);stream.map(Integer::parseInt).filter(s -> s % 2 == 0).forEach(System.out::println);

4,Stream流终结方法(重点)

终结方法指的是调用完成后,不会返回新Stream了,没法继续使用流了。

Stream****提供的常用终结方法 说明
void forEach(Consumer action) 对此流运算后的元素执行遍历
long count() 统计此流运算后的元素个数
Optional max(Comparator<? super T> comparator) 获取此流运算后的最大值元素
Optional min (Comparator<? super T> comparator) 获取此流运算后的最小值元素

5,收集Stream流

收集Stream流:就是把Stream流操作后的结果转回到集合或者数组中去返回。

Stream流:方便操作集合/数组的手段; 集合/数组:才是开发中的目的

Stream 提供的常用终结方法 说明
R collect(Collector collector) 把流处理后的结果收集到一个指定的集合中去
Object[] toArray() 把流处理后的结果收集到一个数组中去
Collectors 工具类提供了具体的收集方式 说明
public static Collector toList() 把元素收集到List集合中
public static Collector toSet() 把元素收集到Set集合中
public static Collector toMap(Function keyMapper ,
Function valueMapper)
把元素收集到Map集合中
两个参数分别为每一个k和每一个v

二,File类

要使用类和之前的思路一样,肯定是要获取到对象。两种方法,一种是通过静态方法,另一种就是通过构造方法。File不能通过静态方法获取的对象。那么就是构造方法啦,下面就来学习构造方法

构造器 说明
public File(String pathname) 根据文件路径创建文件对象
public File(String parent, String child) 根据父路径和子路径名字创建文件对象
public File(File parent, String child) 根据父路径对应文件对象和子路径名字创建文件对象

注意:

  1. File既可代表文件,也可以代表文件夹。File封装的对象仅仅是一个路径名称,这个路径可以是存在也可以是不存在的,也允许<这个到后面的io就会理解,因为如果不存在那么java会帮我们创建>
  2. 需求我们注意的是:路径中"\“要写成”\\“, 路径中”/"可以直接用

示例代码:

// 1、创建一个File对象,指代某个具体的文件。// 路径分隔符// File f1 = new File("D:/resource/ab.txt");// File f1 = new File("D:\\resource\\ab.txt");File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");System.out.println(f1.length()); // 文件大小File f2 = new File("D:/resource");System.out.println(f2.length());// 注意:File对象可以指代一个不存在的文件路径File f3 = new File("D:/resource/aaaa.txt");System.out.println(f3.length());System.out.println(f3.exists()); // false// 我现在要定位的文件是在模块中,应该怎么定位呢?// 绝对路径:带盘符的// File f4 = new File("D:\\code\\javasepromax\\file-io-app\\src\\itheima.txt");// 相对路径(重点):不带盘符,默认是直接去工程下寻找文件的。File f4 = new File("file-io-app\\src\\itheima.txt");System.out.println(f4.length());

在学习方法之前还需要了解两个概念绝对路径和相对路径:<在后面常用>:

绝对路径:

相对于盘符,即 C盘,D盘

File file1 = new File(“D:\\demo\\a.txt”);

相对路径:

在idea中是相对于项目目录:

File file3 = new File(“模块名\\a.txt”);

下面就来学习相对方法:

常用方法1:判断文件类型,获取文件信息

方法名称 说明
public boolean exists() 判断当前文件对象,对应的文件路径是否存在,存在返回true
public boolean isFile() 判断当前文件对象指代的是否是文件,是文件返回true,反之。
public boolean isDirectory() 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。
public String getName() 获取文件的名称(包含后缀)
public long length() 获取文件的大小,返回字节个数
public long lastModified() 获取文件的最后修改时间。
public String getPath() 获取创建文件对象时,使用的路径 <也就是构造器中的路径,给相对就是相对>
public String getAbsolutePath() 获取绝对路径

示例代码:

// 1.创建文件对象,指代某个文件
File f1 = new File("D:/resource/ab.txt");
//File f1 = new File("D:/resource/");// 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());// 除了这些判断功能还有一些获取的功能
File f1 = new File("D:/resource/ab.txt");// 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");
System.out.println(sdf.format(time));// 8.public String getPath():获取创建文件对象时,使用的路径
File f2 = new File("D:\\resource\\ab.txt");
File f3 = new File("file-io-app\\src\\itheima.txt");
System.out.println(f2.getPath());
System.out.println(f3.getPath());// 9.public String getAbsolutePath():获取绝对路径
System.out.println(f2.getAbsolutePath());
System.out.println(f3.getAbsolutePath());

常用方法2:创建文件,删除文件

方法名称 说明
public boolean createNewFile() 创建一个新的空的文件
public boolean mkdir() 只能创建一级文件夹
public boolean mkdirs() 可以创建多级文件夹
方法名称 说明
public boolean delete() 删除文件、空文件夹
// 1、public boolean createNewFile():创建一个新文件(文件内容为空),创建成功返回true,反之。
File f1 = new File("D:/resource/itheima2.txt");
System.out.println(f1.createNewFile());// 2、public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹
File f2 = new File("D:/resource/aaa");
System.out.println(f2.mkdir());// 3、public boolean mkdirs():用于创建文件夹,注意:可以创建多级文件夹
File f3 = new File("D:/resource/bbb/ccc/ddd/eee/fff/ggg");
System.out.println(f3.mkdirs());// 3、public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹。
System.out.println(f1.delete());
System.out.println(f2.delete());
File f4 = new File("D:/resource");
System.out.println(f4.delete());
1.mkdir(): 只能创建单级文件夹、
2.mkdirs(): 才能创建多级文件夹
3.delete(): 文件可以直接删除,但是文件夹只能删除空的文件夹,文件夹有内容删除不了。并且删除后的文件不仅回收站

常用方法3:遍历文件夹

方法名称 说明
public String[] list() 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
public File[] listFiles() 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
// 1、public String[] list():获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
File f1 = new File("D:\\course\\待研发内容");
String[] names = f1.list();
for (String name : names) {System.out.println(name);
}// 2、public File[] listFiles():(重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
File[] files = f1.listFiles();
for (File file : files) {System.out.println(file.getAbsolutePath());
}File f = new File("D:/resource/aaa");
File[] files1 = f.listFiles();
System.out.println(Arrays.toString(files1));

文件的遍历中的几个注意事项:

1.当主调是文件时,或者路径不存在时,返回null
2.当主调是空文件夹时,返回一个长度为0的数组
3.当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹路径放在File数组中,并把数组返回
4.当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在FIle数组中,包含隐藏文件
5.当主调是一个文件夹,但是没有权限访问时,返回null

三,递归

1,认识递归

什么是递归?

递归是一种算法,从形式上来说,方法调用自己的形式称之为递归。

递归的形式: 有直接递归、间接递归,如下面的代码。

public class RecursionTest1 {public static void main(String[] args) {test1();}// 直接方法递归public static void test1(){System.out.println("----test1---");test1(); // 直接方法递归}// 间接方法递归public static void test2(){System.out.println("---test2---");test3();}public static void test3(){test2(); // 间接递归}
}
// 上面只是对递归的形式做一个说明,不具有实际意义

直接递归就是自己调用自己的方法。间接递归是自己调用别的方法,但是别的方法又调用了自己的方法。

从需求来学习:之前我们可能学过阶层,可以通过基础的java代码得到结果,那么怎样通过递归来获取呢?

假设f(n)表示n的阶乘,那么我们可以推导出下面的式子f(5) = 1+2+3+4+5f(5) = f(4)+5f(4) = f(3)+4f(3) = f(2)+3f(2) = f(1)+2f(1) = 1

可以推导是一个公式:

即: f(n) = f(n-1) * n

我们也会发现一个出口:

就是f(1) =1的时候,这个时候我们就无法在套用公式,这个就是我们的递归出口。

总结一下,递归的三个条件

1. 要有递归公式
2. 要有递归出口 / 终止条件
3. 递归的方法必须走向递归出口

比如计算阶层的方法可以这样写:

    public static void main(String[] args) {System.out.println("5的阶乘是:" + f(5));}//求n个数的阶乘public static int f(int n){// 递归出口if(n == 1){return 1;}else {// 递归体return f(n - 1) * n;}}

综合案例:

从指定的文件夹找出所有符合或者包含条件的文件:并打印

public static void main(String[] args) throws Exception {searchFile(new File("D:/") , "QQ.exe");}/*** 去目录下搜索某个文件* @param dir  目录* @param fileName 要搜索的文件名称*/public static void searchFile(File dir, String fileName) throws Exception {// 1、把非法的情况都拦截住if(dir == null || !dir.exists() || dir.isFile()){return; // 代表无法搜索}// 2、dir不是null,存在,一定是目录对象。// 获取当前目录下的全部一级文件对象。File[] files = dir.listFiles();// 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象。if(files != null && files.length > 0){// 4、遍历全部一级文件对象。for (File f : files) {// 5、判断文件是否是文件,还是文件夹if(f.isFile()){// 是文件,判断这个文件名是否是我们要找的if(f.getName().contains(fileName)){System.out.println("找到了:" + f.getAbsolutePath());Runtime runtime = Runtime.getRuntime();runtime.exec(f.getAbsolutePath());}}else {// 是文件夹,继续重复这个过程(递归)searchFile(f, fileName);}}}}

Map集合、Stream流、File类、递归相关推荐

  1. map集合-stream流-BigDecimal

    可能大伙儿经常遇到一些需要计算的字段,但是处理起来又听麻烦的,我这边正好整理了一点点,随便发一发 private static Map<String, BigDecimal> object ...

  2. java(九)-方法引用, Stream流,File类 , 递归 ,字节流

    day09[方法引用.Lambda表达式.Stream流] 今日目标 线程状态 等待与唤醒 Lambda表达式 Stream流 教学目标 能够说出线程6个状态的名称 能够理解等待唤醒案例 能够掌握La ...

  3. 不可变集合 Stream流 异常

    目录 创建不可变集合 如何创建不可变集合? Stream流 Stream流的概述 Stream流的获取 Stream流的常用API Stream流的综合应用 收集Stream流 异常处理 异常概述.体 ...

  4. 13-1 IO流 ---- File类的使用(2)常用方法

    13-1 IO流 ---- File类的使用(2)常用方法 一.File类的获取功能 public String getAbsolutePath():获取绝对路径 public String getP ...

  5. 15.方法引用, Stream流,File类 , 递归 ,字节流

    JavaSE高级 Lambda表达式.方法引用.Stream流.File类 第一章 JDK8新特性 JDK新特性: Lambda 表达式 默认方法[已学习过] Stream API 方法引用 Base ...

  6. Map集合 File类 递归 序列化 常用类 进程线程 死锁

    一.Map集合 将键映射到值得对象,键得值不能重复,一个键可以对应最少一个值. Map接口下的封装好得实现类 –|HashMap –|TreeMap 1.Map接口下的方法 增://将指定得值与该映射 ...

  7. Java8新特性-使用Stream流来实现递归遍历树形结构(案例)

    Java8新特性-Stream流 可能平常会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来 ...

  8. 第八章_集合(3)_Map集合Stream流

    目录 一.Map 1.Map集合的基本使用 2.Map集合的常用方法 3.Map集合遍历 二.HashMap 三.TreeMap 四.可变参数 五.Stream流 1.Stream流概念 2.获取St ...

  9. Map集合转换成实体类对象,实体类对象转换为map集合,互转工具类

    注 : 2019-06-16日 增加第六节 map与实体互转工具类,直接看第6节; 1.调用这个方法BeanMapUtils.mapToBean(),实现map集合转实体类对象; 注意: 这个方法转换 ...

  10. 09、IO流—File类与IO流

    文章目录 一.File类 基本认识 实用方法 获取功能 重命名功能(包含剪切) 判断功能 创建.删除文件 实际小案例 二.IO流 1.认识IO流 2.IO流基类介绍 字节流基类介绍 字符流基类介绍 三 ...

最新文章

  1. scss安装_安装了这9个免费PS插件后,终于能正常时间下班了……
  2. Java是发展的垫脚石。 学习吧!
  3. 树莓派 鼠标延迟问题【Linux】
  4. 递归遍历树结构顺序显示并且添加到list集合
  5. c语言中变量的属性,C中的属性变量
  6. C/C++ 常见误区
  7. POJ-2034 Anti-prime Sequences dfs
  8. Cascadea for Mac(强大的CSS编辑器)
  9. 将rdd存储到本地的一个文件中
  10. 如何把pdf转换成ezd_电脑怎么把pdf转换成ppt
  11. 数据化运营之会员数据化运营
  12. pcb成型板aoi检测_PCB设备:一款新的自动光学检测(AOI)系统
  13. 验证苹果手机正品新机
  14. java中BOM是什么_Java处理带BOM的文本情况是什么?
  15. matlab 数组中的一个值,MATLAB数组元素引用的三种方法
  16. An element could not be located on the page using the given search parameters.
  17. connect() failed (111: Connection refused) while connecting to upstream 解决方法
  18. 秀场直播的四种实现方式,让我们从方案架构进行分析
  19. 基于wifi无线PLC远程控制实现io开关量信号远程采集传输技术
  20. 无稳态多谐震荡器学习

热门文章

  1. Xilinx 异步FIFO核实现FPGA与DSP通过UPP(通用并口)进行数据传输
  2. 电脑店U盘PE系统取消赞助商主页、软件的方法
  3. 深度学习哪家强?用数据来一较高下吧
  4. 黑马Matplotlib学习笔记
  5. HBase开发SQL查询中间件之查询原理
  6. 2022年2月编程语言排行榜:TIOBE指数前3名受益于技术变革
  7. 文献资源最多的文献下载神器,99.99%的文献都可下载
  8. 探索生活神奇:海尔智家小件品牌战略暨新品发布引爆AWE
  9. Box2D中切割刚体效果的实现一览(二)
  10. 2012年的中国移动互联网