Java进阶5 Stream流、File类


Stream流与File类

  • 导图
  • 一、Stream流
    • 1.1 Stream流体验
    • 1.2 Stream流的创建
    • 1.3 Stream流中间方法
    • 1.4、Stream流终结方法
  • 二、File类
    • 2.1、File对象的创建
    • 2.2、File判断和获取方法
    • 2.3、创建和删除方法
    • 2.4、遍历文件夹方法
    • 2.5、使用递归搜索文件


导图

Java进阶5 Stream流、File类_第1张图片

一、Stream流

Stream流(Stream API),它是从JDK8以后来有的新特性,是专业用于 对集合或者数组进行便捷操作的。

1.1 Stream流体验

案例需求:现有一个List集合,元素有 “张三丰”,“张无忌”,“周芷若”,“赵敏”,“张强”,现在需要找出姓张的人,且是3个字的名字,存入到一个新集合中去。

集合做法

List<String> names = new ArrayList<>();
Collections.addAll(names, "张三丰","张无忌","周芷若","赵敏","张强");
System.out.println(names);

传统做法

List<String> list = new ArrayList<>();
for (String name : names) {
    if(name.startsWith("张") && name.length() == 3){
        list.add(name);
    }
}
System.out.println(list);

Stream流做法

List<String> list2 = names.stream().filter(s -> s.startsWith("张")).filter(a -> a.length()==3).collect(Collectors.toList());
System.out.println(list2);

1.2 Stream流的创建

体验完Stream流的创建后,接下来正式介绍Stream流,首先先看Stream流的创建(获取Stream流)。

Java进阶5 Stream流、File类_第2张图片

Stream流的创建主要掌握以下四点:

  1. 如何获取List集合的Stream流?
  2. 如何获取Set集合的Stream流?
  3. 如何获取Map集合的Stream流?
  4. 如何获取数组的Stream流?

代码实现

public static void main(String[] args) {
        //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(names,"刘德华","张曼玉","蜘蛛精","马德","德玛西亚");
        Stream<String> stream1 = names.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> vlaues = map.values();
        Stream<Double> vs = vlaues.stream();

        Set<Map.Entry<String,Double>> entries = map.entrySet();
        Stream<Map.Entry<String, Double>> stream2 = entries.stream();
        stream2.filter(e->e.getKey().contains("巴")).forEach(e-> System.out.println(e.getKey()+ "---" + e.getValue()));

        //4.数组的Stream流
        String[] names3 = {"张翠山", "东方不败", "唐大山", "独孤求败"};
        Stream<String> s1 = Arrays.stream(names3);
        Stream<String>s2 = Stream.of(names3);
    }

1.3 Stream流中间方法

中间方法:调用完方法之后其结果是一个新的Stream流,于是可以继续调用方法,这样一来就可以支持链式编程(或者叫流程式编程)

Java进阶5 Stream流、File类_第3张图片

Stream提供的常用中间方法

Java进阶5 Stream流、File类_第4张图片

中间方法的使用演示

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {

        List<Double> list = new ArrayList<>();
        Collections.addAll(list,88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0);
        //需求1:找出成绩大于60分的数据,并升序后,再输出。
        list.stream().filter(s->s >= 60).sorted().forEach(s-> System.out.println(s));

        List<Student> students = new ArrayList<>();
        Student s1 = new Student("蜘蛛精", 26, 172.5);
        Student s2 = new Student("蜘蛛精", 26, 172.5);
        Student s3 = new Student("紫霞", 23, 167.6);
        Student s4 = new Student("白晶晶", 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(o1.getHeight(), o1.getHeight()))
                .limit(3).forEach(System.out::println);
        System.out.println("=================================");

        //需求4:取出身高倒数的2名学生,并输出。
        students.stream().sorted(((o1, o2) -> Double.compare(o2.getHeight(), o2.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);
    }
}

1.4、Stream流终结方法

Stream流的终结方法,这些方法的特点是,调用完方法之后,其结果就不再是Stream流了,所以不支持链式编程。

Java进阶5 Stream流、File类_第5张图片

常用的终结方法

Java进阶5 Stream流、File类_第6张图片

代码使用演示

public class StreamTest4 {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        Student s1 = new Student("蜘蛛精", 26, 172.5);
        Student s2 = new Student("蜘蛛精", 26, 172.5);
        Student s3 = new Student("紫霞", 23, 167.6);
        Student s4 = new Student("白晶晶", 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);
        // 需求1:请计算出身高超过168的学生有几人。
        long size = students.stream().filter(s -> s.getHeight() > 168).count();
        System.out.println(size);

        // 需求2:请找出身高最高的学生对象,并输出。
        Student s = students.stream().max((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight())).get();
        System.out.println(s);

        // 需求3:请找出身高最矮的学生对象,并输出。
        Student ss = students.stream().min((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight())).get();
        System.out.println(ss);

        // 需求4:请找出身高超过170的学生对象,并放到一个新集合中去返回。
        // 流只能收集一次。
        List<Student> students1 = students.stream().filter(a -> a.getHeight() > 170).collect(Collectors.toList());
        System.out.println(students1);

        Set<Student> students2 = students.stream().filter(a -> a.getHeight() > 170).collect(Collectors.toSet());
        System.out.println(students2);

        // 需求5:请找出身高超过170的学生对象,并把学生对象的名字和身高,存入到一个Map集合返回。
        Map<String, Double> map =
                students.stream().filter(a -> a.getHeight() > 170)
                        .distinct().collect(Collectors.toMap(a -> a.getName(), a -> a.getHeight()));
        System.out.println(map);

        // Object[] arr = students.stream().filter(a -> a.getHeight() > 170).toArray();
        Student[] arr = students.stream().filter(a -> a.getHeight() > 170).toArray(len -> new Student[len]);
        System.out.println(Arrays.toString(arr));
    }
}

二、File类

File类:表示当前系统下的文件(也可以是文件夹)。

通过file类提供的方法可以获取文件大小、判断文件是否存在、创建文件、创建文件夹等。

注意:

File对象只能对文件进行操作,不能操作文件中的内容。

2.1、File对象的创建

File类使用的第一步就是创建File类的对象,但想要创建对象,得先了解File类有哪些构造器。

Java进阶5 Stream流、File类_第7张图片

File类创建对象的代码演示

注意:路径中"" 要写成 “\”,而"/"可以直接使用。

public class FileTest1 {
    public static void main(String[] args) {
        // 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("console.txt");
        System.out.println(f4.length());
    }
}

2.2、File判断和获取方法

刚才创建File对象的时候,会传递一个文件路径过来,但是File对象封装的路径到底存不存在,或者是文件夹还是文件,其实都是不清楚的,所以我们现在要使用File类中的其他方法来判断。

Java进阶5 Stream流、File类_第8张图片

代码演示

public class Test {
    public static void main(String[] args) {
        //1.创建文件对象,指代某个文件
        File file = new File("day/console.txt");

        //2.public boolean exists(); 判断当前文件对象,对应的文件路径是否存在,存在返回true.
        System.out.println(file.exists());

        //3.public boolean isFile(); 判断当前文件对象指代的是否是文件,是文件返回true,反之。
        System.out.println(file.isFile());

        //4.public boolean isDirectory();判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。
        System.out.println(file.isDirectory());
    }
}

当然,除了判断以外,还有一些获取功能。

File f1 = new File("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("ab.txt");
File f3 = new File("console.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.3、创建和删除方法

File类还提供了创建和删除文件的方法,如下所示:

public class FileTest3 {
    public static void main(String[] args) throws Exception {
        // 1、public boolean createNewFile():创建一个新文件(文件内容为空),创建成功返回true,反之。
        File f1 = new File("console.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():文件可以直接删除,但是文件夹只能删除空的文件夹,文件夹有内容则删除不了。

2.4、遍历文件夹方法

如何获取一个文件夹中的内容? 在File类中也是有相应方法的,如下所示:

Java进阶5 Stream流、File类_第9张图片

public class FileTest4 {
    public static void main(String[] args) {
        // 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.当主调是文件时,或者路径不存在时,返回nul。
2.当主调是空文件夹时,返回一个长度为0的数组。
3.当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹路径放在File数组中,并把数组返回。
4.当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中,包含隐藏文件。
5.当主调是一个文件夹,但是没有权限访问时,返回null。


2.5、使用递归搜索文件

当要查询或修改多层文件夹时,一次File类方法执行是不够的,这时候就可以使用递归来遍历文件夹。

案例需求:在D:\\判断下搜索QQ.exe这个文件,然后直接输出。

1.先调用文件夹的listFiles方法,获取文件夹的一级内容,得到一个数组
2.然后再遍历数组,获取数组中的File对象
3.因为File对象可能是文件也可能是文件夹,所以接下来就需要判断
	判断File对象如果是文件,就获取文件名,如果文件名是`QQ.exe`则打印,否则不打印
	判断File对象如果是文件夹,就递归执行1,2,3步骤
所以:把1,2,3步骤写成方法,递归调用即可。

代码实现

public class Test3 {
    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);
                }
            }
        }
    }
}

你可能感兴趣的:(Java进阶,java,开发语言)