公子奇带你进入Java8流的世界(二)

    在上一篇中咱们带领你们简单的了解流的概念及使用场景,知道了流的本质操做是将外部迭代转为了内部迭代,由此程序并发性上获得了很大的优化。不过咱们在面对复杂的需求是又如何经过流来操做呢?在本节咱们就来好好的介绍流的常见用法,以此来处理复杂数据,以及流的其余类型:数值流、文件流以及无限流等内容。java

1、筛选和切片

    对于一串流,咱们有时须要取出咱们须要的流中某些元素,例如:符合某些条件的元素、只须要流中的某一段等。主要是经过谓词筛选。数组

  一、咱们如何去除流中重复的元素,以及什么样的元素是重复元素呢?流中提供了一个distinct方法来实现。并发

  二、如何取出流中某一段长度的流,流中提供了一个limit方法来知足咱们的需求。dom

  三、若咱们须要跳过流中的某一段,又该如何作呢?一样Java8中也提供了一个skip方法来知足咱们跳过固定长度的流。ide

    下面咱们带着这三个疑问及提示用代码来讲明问题。优化

    首先定义一个POJO,后续操做都基于此来实例化元素。this

 1 package com.hz;
 2 
 3 /**
 4  * 民警实体类
 5  */
 6 public class Police {
 7     /**
 8      * 民警警号
 9      */
10     private String policeNo;
11     /**
12      * 民警姓名
13      */
14     private String policeName;
15     /**
16      * 民警年龄
17      */
18     private Integer policeAge;
19     /**
20      * 是否退休
21      */
22     private boolean policeIsRetire;
23 
24     public Police(String policeNo, String policeName, Integer policeAge, boolean policeIsRetire) {
25         this.policeNo = policeNo;
26         this.policeName = policeName;
27         this.policeAge = policeAge;
28         this.policeIsRetire = policeIsRetire;
29     }
30 
31     public String getPoliceNo() {
32         return policeNo;
33     }
34 
35     public void setPoliceNo(String policeNo) {
36         this.policeNo = policeNo;
37     }
38 
39     public String getPoliceName() {
40         return policeName;
41     }
42 
43     public void setPoliceName(String policeName) {
44         this.policeName = policeName;
45     }
46 
47     public Integer getPoliceAge() {
48         return policeAge;
49     }
50 
51     public void setPoliceAge(Integer policeAge) {
52         this.policeAge = policeAge;
53     }
54 
55     public boolean isPoliceIsRetire() {
56         return policeIsRetire;
57     }
58 
59     public void setPoliceIsRetire(boolean policeIsRetire) {
60         this.policeIsRetire = policeIsRetire;
61     }
62 
63     @Override
64     public String toString() {
65         return "Police{" +
66                 "policeNo='" + policeNo + '\'' +
67                 ", policeName='" + policeName + '\'' +
68                 ", policeAge=" + policeAge +
69                 ", policeIsRetire='" + policeIsRetire + '\'' +
70                 '}';
71     }
72 
73     @Override
74     public boolean equals(Object o) {
75         if (this == o) return true;
76         if (!(o instanceof Police)) return false;
77 
78         Police police = (Police) o;
79 
80         if (policeIsRetire != police.policeIsRetire) return false;
81         if (!policeNo.equals(police.policeNo)) return false;
82         if (!policeName.equals(police.policeName)) return false;
83         return policeAge.equals(police.policeAge);
84     }
85 
86     @Override
87     public int hashCode() {
88         int result = policeNo.hashCode();
89         result = 31 * result + policeName.hashCode();
90         result = 31 * result + policeAge.hashCode();
91         result = 31 * result + (policeIsRetire ? 1 : 0);
92         return result;
93     }
94 }
 1 package com.hz;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 
 6 import static java.util.stream.Collectors.toList;
 7 
 8 /**
 9  * 筛选某些元素
10  * 包含:filter / distinct / limit / skip
11  */
12 public class FilterAndLimitStreamDemo {
13     public static void main(String[] args) {
14         List<Police> policeList = Arrays.asList(
15                 new Police("P001", "余警官", 27, false),
16                 new Police("P002", "李警官", 32, false),
17                 new Police("P003", "程警官", 25, false),
18                 new Police("P004", "杨警官", 35, false),
19                 new Police("P005", "张警官", 70, true),
20                 new Police("P006", "王警官", 68, true),
21                 new Police("P007", "赵警官", 77, true),
22                 new Police("P008", "刘警官", 64, true),
23                 new Police("P008", "刘警官", 64, true)
24         );
25 
26         //***** 1-使用谓词筛选
27         List<Police> filterPolices = policeList.stream().filter(Police::isPoliceIsRetire).collect(toList());
28         System.out.println("结果1: " + filterPolices);
29 
30         System.out.println("---------------- 分割线 ---------------------");
31 
32         //***** 2-筛选 大于60岁 并 去除重复的数据(是否重复 根据HashCode和equal决定 二者同时)
33         policeList.stream().filter(p -> p.getPoliceAge() > 60).distinct().forEach(System.out :: println);
34 
35         System.out.println("---------------- 分割线 ---------------------");
36 
37         //***** 3-截流 截取前三位退休的民警
38         policeList.stream().filter(Police :: isPoliceIsRetire).limit(3).forEach(System.out :: println);
39 
40         System.out.println("---------------- 分割线 ---------------------");
41 
42         //***** 4-跳过几个元素 获取退休民警 并跳过前两位退休民警
43         policeList.stream().filter(Police :: isPoliceIsRetire).skip(2).forEach(System.out :: println);
44     }
45 }

2、映射

    映射即将流中的元素进行处理后返回新的流,即从某些对象中选择信息。在SQL语言中,咱们一般会取出表中的某个字段信息,将其返回给页面展现,若在Java语言中,如何实现一样的功能呢?语言也提供了两个方法让咱们来实现。spa

  一、map:该方法会对流中的每一个元素进行处理,咱们能够理解为将流中的每一个元素进行转换后返回一个新的流。例如咱们如何取出全部民警的姓名。code

  二、flatMap:既然有了map方法,Java又为何提供一个flatMap呢?此为流的扁平化。咱们以前讲解过,小的流和组成一个大的流,若咱们有个大的流,大的流中有多少小的流咱们并不知道,此时咱们没法对每一个小的流再次进行处理,而flatMap方法便可解决咱们的问题,它能够将大流中的小流的值组成一个新的大流,以后再对该流进行元素处理。例如咱们须要将多个单词重复的字母给去除,此时每一个单词便可组装为一个小流,若咱们使用map来处理,只会将每一个单词本身的重复字母给去除,两个单词之间的重复字母没法去除。对象

 1 package com.hz;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 import java.util.stream.Stream;
 6 
 7 import static java.util.stream.Collectors.toList;
 8 
 9 /**
10  * 流中映射
11  */
12 public class StreamMapDemo {
13     public static void main(String[] args) {
14         List<Police> policeList = Arrays.asList(
15                 new Police("P001", "余警官", 27, false),
16                 new Police("P002", "李警官", 32, false),
17                 new Police("P003", "程警官", 25, false),
18                 new Police("P004", "杨警官", 35, false),
19                 new Police("P005", "张警官", 70, true),
20                 new Police("P006", "司马警官", 68, true),
21                 new Police("P007", "赵科", 77, true),
22                 new Police("P008", "刘警官", 64, true),
23                 new Police("P008", "刘警官", 64, true)
24         );
25 
26         //***** 1-对流元素中的字段进行处理 获取民警的姓名     和      获取民警姓名长度
27         policeList.stream().map(Police :: getPoliceName).forEach(System.out :: println);
28 
29         List<Integer> policesNameLength = policeList.stream().map(Police::getPoliceName).map(String::length).collect(toList());
30         System.out.println("结果: " + policesNameLength);
31 
32         System.out.println("------------ 分割线 ----------------");
33 
34         //***** 2-流的扁平化 将一组单词 重复的字母去除
35         String[] words = {"gong", "zi", "chuan", "qi"};
36         Stream<String> wordsStream = Arrays.stream(words); //将数组转为流对象
37         Stream<String> wordsStream2 = Arrays.stream(words); //将数组转为流对象
38 
39         //此时为 将每一个单词为一个数组转为一个流即四个流  流自己没有重复   两个流之间是存在重复的
40         List<Stream<String>> streamsList = wordsStream.map(s -> s.split("")).map(Arrays::stream).distinct().collect(toList());
41         System.out.println(streamsList);
42         //wordsStream为一个流 不可屡次使用
43         // java8中有个扁平化的处理 为将流中的值组成一个大的流 flatMap
44         List<String> disWordsList = wordsStream2.map(s -> s.split("")).flatMap(Arrays::stream).distinct().collect(toList());
45         System.out.println("结果:" + disWordsList);
46 
47         System.out.println("---------------- 分割线 --------------------");
48 
49         //***** 3-一个实例 给定两个数字列表,如何返回全部的数对呢?
50         //          例如,给定列表[1, 2, 3]和列表[3, 4],应该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]
51         Integer[] ints1 = {1, 2, 3};
52         Integer[] ints2 = {3, 4};
53 
54 //        List<List<int[]>> result = Arrays.stream(ints1).map(i -> {
55 //            List<int[]> tempList = Arrays.stream(ints2).map(j -> {
56 ////                int[] temp = new int[2];
57 ////                temp[0] = i;
58 ////                temp[1] = j;
59 ////                return temp;
60 //                return new int[]{i, j};
61 //            }).collect(toList());
62 //            return tempList;
63 //        }).collect(toList());
64 
65         //更简化
66         List<List<int[]>> result = Arrays.stream(ints1).map(i -> Arrays.stream(ints2).map(j -> new int[]{i, j}).collect(toList())).collect(toList());
67 
68         result.forEach(l -> l.forEach(is -> System.out.println((is[0] + "," + is[1]))));
69     }
70 }

3、查找和匹配

    有时咱们须要查看数据集中的某些元素是否匹配一个给定的属性。对于该需求,Java中分别提供了 allMatch 、 anyMatch 、 noneMatch 、 findFirst 和 findAny 方法来知足咱们。

  一、allMatch:该方法表示流中的全部元素都知足咱们的条件。例如咱们想知道当前的民警容器中是否是全部的民警都为退休民警。

  二、anyMatch:该方法表示流中的元素至少有一个知足咱们的条件。例如咱们想知道有没有民警退休了。

  三、noneMatch:表示全部的元素都不知足。它与allMatch正好相反。

  四、findFirst:在流中找出第一个元素,该方法咱们通常会配合筛选来使用。

  五、findAny:在流中随意找出一个元素,通常状况下方法返回给咱们的都为第一个元素。

 1 package com.hz;
 2 
 3 import java.util.*;
 4 
 5 /**
 6  * 流中查找和匹配
 7  */
 8 public class FindAndMatchDemo {
 9     public static void main(String[] args) {
10         List<Police> policeList = Arrays.asList(
11                 new Police("P001", "余警官", 27, false),
12                 new Police("P002", "李警官", 32, false),
13                 new Police("P003", "程警官", 25, false),
14                 new Police("P004", "杨警官", 35, false),
15                 new Police("P005", "张警官", 70, true),
16                 new Police("P006", "司马警官", 68, true),
17                 new Police("P007", "赵科", 77, true),
18                 new Police("P008", "刘警官", 64, true),
19                 new Police("P008", "刘警官", 64, true)
20         );
21 
22         //***** 1-检查流中元素至少匹配一个  民警列表中至少有一名退休民警
23         System.out.println("--------------- anyMatch分割线 ------------------");
24         if (policeList.stream().anyMatch(Police :: isPoliceIsRetire)) {
25             System.out.println("列表存在退休民警...");
26         } else {
27             System.out.println("当前没有退休民警...");
28         }
29 
30         System.out.println("----------- allMatch分割线 ------------");
31 
32         //***** 2-检查流中是否匹配全部元素  是否为退休民警列表
33         if (policeList.stream().allMatch(Police :: isPoliceIsRetire)) {
34             System.out.println("该列表为一个退休民警列表...");
35         } else {
36             System.out.println("该列表中存在未退休的民警...");
37         }
38 
39         System.out.println("------------- noneMatch分割线 -----------");
40         //与allMatch对应的是noneMatch 即全部都不匹配
41         if (policeList.stream().noneMatch(Police::isPoliceIsRetire)) {
42             System.out.println("该列表都不是退休民警");
43         } else {
44             System.out.println("该列表存在退休民警");
45         }
46 
47         System.out.println("--------------- 查找分割线 --------------------");
48 
49         //***** 3-查找元素 从民警列表中找出任一元素
50         Optional<Police> anyPolice = policeList.stream().findAny();
51         System.out.println(anyPolice);
52         //在这里Optional这是一个容器类,该容器中只能存储一个对象 其中Optional中实现了一些方法用来操做和判断该容器是否有值
53         //这里咱们简单了解下,详细后面咱们在好好介绍下该类
54         //***** 案例:找出任意一个退休民警 并打印该民警姓名       ifPresent如有值则执行
55         policeList.stream().filter(Police :: isPoliceIsRetire).findAny().ifPresent(p -> System.out.println(p.getPoliceName()));
56         boolean hasValue = policeList.stream().filter(Police::isPoliceIsRetire).findAny().isPresent(); //是否有值isPresent
57         System.out.println("容器中是否有匹配的值:" + hasValue);
58         // 若容器中有值则返回,不然返回一个默认的值
59         Police police = policeList.stream().filter(Police :: isPoliceIsRetire).findAny().orElse(new Police("","",0, false));
60         System.out.println("返回民警: " + police);
61         //获取匹配的民警 有则返回  没有则异常java.util.NoSuchElementException: No value present
62         Police police1 = policeList.stream().filter(Police::isPoliceIsRetire).findAny().get();
63         System.out.println("获取民警: " + police1);
64 
65         System.out.println("---------------");
66         //***** 4-查找流中第一个元素
67         Police police2 = policeList.stream().filter(Police::isPoliceIsRetire).findFirst().get();
68         System.out.println("结果: " + police2);
69     }
70 }

4、归约

    以上提供的方法,咱们会发现返回给咱们的都是一个boolean类型、无返回或为一个容器,但是咱们有时须要将流中的每一个元素从新组合来获得结果。这就须要将流中全部的元素结合着来处理,此时就须要归约。

  一、例如将流中全部民警的年龄求和。固然使用for-each能够实现,可在这里咱们还有更好的方式吗?

  二、咱们须要当前监狱年龄最大的民警和年龄最小的民警。此时又该如何实现呢?咱们总不至于要将全部的民警挨个遍历一篇吧!

    以上两个问题其实都是能够经过归约获得很好的解决,除此之外,咱们会发现年龄都是与数值相关的,这也将引出咱们普通流的变种,即数值流。下面以代码来讲明问题:

package com.hz;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class ReduceDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 4, 3, 9);

        //***** 1-将一组数值求和
        Integer sum = numbers.stream().reduce(0, (a, b) -> a + b);
        System.out.println("sum: " + sum);
        //若reduce未指定第一个参数,则不知实际返回类型,此时语言自己返回一个Optional容器对象
        Optional<Integer> sumOptional = numbers.stream().reduce((a, b) -> a + b);
        System.out.println("sum-optional: " + sumOptional);
        //变化
        sum = numbers.stream().reduce(0, Integer :: sum);
        System.out.println("sum2: " + sum);

        System.out.println("------------ 分割线 --------------");

        //***** 2-获取一组数的最大和最小值
        Optional<Integer> max = numbers.stream().reduce(Integer::max);
        System.out.println("max: " + max);

        Optional<Integer> min = numbers.stream().reduce(Integer :: min);
        System.out.println("min: " + min);

        System.out.println("---------- 分割线 --------");

        //**** 3-一个案例:使用map和reduce统计民警列表中有多少民警
        List<Police> policeList = Arrays.asList(
                new Police("P001", "余警官", 27, false),
                new Police("P002", "李警官", 32, false),
                new Police("P003", "程警官", 25, false),
                new Police("P004", "杨警官", 35, false),
                new Police("P005", "张警官", 70, true),
                new Police("P006", "司马警官", 68, true),
                new Police("P007", "赵科", 77, true),
                new Police("P008", "刘警官", 64, true)
        );

        Integer policeNum = policeList.stream().map(p -> 1).reduce(0, Integer::sum);
        System.out.println("列表中民警数量: " + policeNum);
    }
}

5、一个实例

    关于流的这么多操做,咱们上面都说了不少,可是在实际需求中咱们应该如何的灵活运用呢?下面咱们经过一些问题案例来总结一下流运用。

  (1) 找出2019年入职的民警,并按年龄排序(从低到高)。
  (2) 民警籍贯都在哪里?
  (3) 查找全部来自于浙江的民警,并按姓名排序。
  (4) 返回全部民警的警号,并按警号顺序排序。
  (5) 有没有民警籍贯是在安徽的?
  (6) 获取籍贯为浙江的民警的年龄之和
  (7) 全部民警中,年龄最大的是多少?
  (8) 找到民警中年龄最小的民警

package com.hz;

import java.util.*;

/**
 * 关于流操做的一个案例
 */
public class StreamDemo {
    public static void main(String[] args) {
        List<Police> polices = Arrays.asList(
                new Police("P001", "Y警官", 27, "浙江", 2019),
                new Police("P002", "L警官", 32, "安徽", 2019),
                new Police("P003", "C警官", 25, "安徽", 2015),
                new Police("P004", "Y警官", 35, "浙江", 2015),
                new Police("P005", "Z警官", 31, "上海", 2018),
                new Police("P006", "W警官", 42, "浙江", 2018),
                new Police("P007", "Z警官", 31, "浙江", 2019),
                new Police("P009", "Z警官", 32, "浙江", 2019),
                new Police("P008", "L警官", 49, "浙江", 2019)
        );

//        (1) 找出2019年入职的民警,并按年龄排序(从低到高)。
        polices.stream().filter(p -> p.getPoliceEntryYear() == 2019).sorted(Comparator.comparing(Police::getPoliceAge)).forEach(System.out::println);

        System.out.println("---------------- 分割线 --------------------------");

//        (2) 民警籍贯都在哪里?
        polices.stream().map(Police::getPoliceNativePlace).distinct().forEach(System.out::println);

        System.out.println("---------------- 分割线 --------------------------");

//        (3) 查找全部来自于浙江的民警,并按姓名排序。
        polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).sorted(Comparator.comparing(Police::getPoliceName)).forEach(System.out::println);

        System.out.println("---------------- 分割线 --------------------------");

//        (4) 返回全部民警的警号,并按警号顺序排序。
        polices.stream().map(Police::getPoliceNo).sorted().forEach(System.out::println);

        System.out.println("---------------- 分割线 --------------------------");

//        (5) 有没有民警籍贯是在安徽的?
        if (polices.stream().anyMatch(p -> "安徽".equals(p.getPoliceNativePlace()))) {
            System.out.println("存在籍贯为安徽的民警...");
        } else {
            System.out.println("不存在籍贯为安徽的民警...");
        }

        System.out.println("---------------- 分割线 --------------------------");

//        (6) 获取籍贯为浙江的民警的年龄之和
        Integer ageSum = polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).map(Police::getPoliceAge).reduce(0, Integer::sum);
        //以上方式暗中存在一个装箱操做 其实stream中有个数值流能够省去这个隐藏操做
        ageSum = polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).mapToInt(Police::getPoliceAge).sum();
        System.out.println("全部浙江民警年龄总和:" + ageSum);

        System.out.println("---------------- 分割线 --------------------------");

//        (7) 全部民警中,年龄最大的是多少?
        Optional<Integer> ageMaxOptional = polices.stream().map(Police::getPoliceAge).reduce(Integer::max);
        // 或使用流的max方法
        ageMaxOptional = polices.stream().max(Comparator.comparing(Police::getPoliceAge)).map(Police::getPoliceAge);
        //一样 该方式也能够转为数值流计算
        OptionalInt maxAgeOp = polices.stream().mapToInt(Police::getPoliceAge).max();
        System.out.println(maxAgeOp.getAsInt());
        if (ageMaxOptional.isPresent()) {
            System.out.println("全部民警最大年龄为: " + ageMaxOptional.get());
        } else {
            System.out.println("没有民警...");
        }

        System.out.println("---------------- 分割线 --------------------------");

//        (8) 找到民警中年龄最小的民警
        Optional<Police> ageMinPoliceOptional = polices.stream().reduce((p1, p2) -> p1.getPoliceAge() < p2.getPoliceAge() ? p1 : p2);
        if (ageMinPoliceOptional.isPresent()) {
            System.out.println("年龄最小的民警: " + ageMinPoliceOptional);
        } else {
            System.out.println("列表中没有民警...");
        }

        //其实还有更加简单的方式,流中有个min方法
        ageMinPoliceOptional = polices.stream().min(Comparator.comparing(Police::getPoliceAge));
        System.out.println(ageMinPoliceOptional);
    }

    static class Police {
        private String policeNo;
        private String policeName;
        private Integer policeAge;
        private Integer policeEntryYear;
        private String policeNativePlace;

        public Police(String policeNo, String policeName, Integer policeAge, String policeNativePlace, Integer policeEntryYear) {
            this.policeNo = policeNo;
            this.policeName = policeName;
            this.policeAge = policeAge;
            this.policeNativePlace = policeNativePlace;
            this.policeEntryYear = policeEntryYear;
        }

        public String getPoliceNo() {
            return policeNo;
        }

        public void setPoliceNo(String policeNo) {
            this.policeNo = policeNo;
        }

        public String getPoliceName() {
            return policeName;
        }

        public void setPoliceName(String policeName) {
            this.policeName = policeName;
        }

        public Integer getPoliceAge() {
            return policeAge;
        }

        public void setPoliceAge(Integer policeAge) {
            this.policeAge = policeAge;
        }

        public String getPoliceNativePlace() {
            return policeNativePlace;
        }

        public void setPoliceNativePlace(String policeNativePlace) {
            this.policeNativePlace = policeNativePlace;
        }

        public Integer getPoliceEntryYear() {
            return policeEntryYear;
        }

        public void setPoliceEntryYear(Integer policeEntryYear) {
            this.policeEntryYear = policeEntryYear;
        }

        @Override
        public String toString() {
            return "Police{" +
                    "policeNo='" + policeNo + '\'' +
                    ", policeName='" + policeName + '\'' +
                    ", policeAge=" + policeAge +
                    ", policeEntryYear='" + policeEntryYear + '\'' +
                    ", policeNativePlace='" + policeNativePlace + '\'' +
                    '}';
        }
    }

}

6、数值流及构建流

    关于Java中流的介绍,咱们也说明的差很少了,流对于表达数据处理查询是很是强大而有用的。不过在上面咱们对流的建立都是基于集合以后作集合转换,但是除了集合以外,咱们还有其余建立流的方式吗?答案是确定的。关于数值流咱们在上节实例中已经作了简单说明,在流的建立过程当中,有时咱们并不知道流的内容,此时须要根据变化来建立流对象。

 1 package com.hz;
 2 
 3 import java.io.IOException;
 4 import java.nio.charset.Charset;
 5 import java.nio.file.Files;
 6 import java.nio.file.Paths;
 7 import java.util.ArrayList;
 8 import java.util.Arrays;
 9 import java.util.List;
10 import java.util.stream.Stream;
11 
12 /**
13  * 咱们以前建立的流都是经过一个List对象或数组
14  * 其余方式也是能够建立流的
15  */
16 public class CreateStreamDemo {
17     public static void main(String[] args) {
18         // 1-List建立流
19         List<String> list = new ArrayList<>();
20         Stream<String> stream = list.stream();
21 
22         // 2-数组建立流
23         String[] strings = {"Gong", "Zi", "Qi"};
24         Stream<String> stream1 = Arrays.stream(strings);
25 
26         // 3-静态方法建立流
27         Stream<String> stream2 = Stream.of("Gong", "Zi", "Qi");
28         Stream.iterate(0, i -> i + 2).limit(10).forEach(System.out::println);
29         Stream<Object> stream4 = Stream.generate(() -> "GongZiQi");
30         //说明: iterate 和 generate 在生成流是须要注意截取,它们均可以作无限流的生成 以下
31 //        Stream.iterate(0, i -> i + 2).forEach(System.out::println); //生成全部偶数 注意
32 //        Stream.generate(Math::random).forEach(System.out::println); //生成全部随机数 0~1之间 注意
33 
34         // 4-文件生成流
35         try {
36             Stream<String> stream3 = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
37         } catch (IOException e) {
38             e.printStackTrace();
39         }
40     }
41 }
相关文章
相关标签/搜索