2.java8新特性之Stream

1.java8两大亮点之Stream

stream直译为流,但它与原IO流完全不同的概念。
简单地说:它是数据的渠道,用于操作数据源所生成的元素的序列,它可以像数据库中的数据一样,使用sql去操作。

  • stream自己不会存储元素
  • stream不会改变源对象,只是返回一个新的stream。
  • Stream操作是延迟执行的,需要执行的时候才会去给出结果。


    流式操作:创建Stream-中间操作-终止操作
    /**
     * 创建Stream
     */
    @Test
    public void test1() {
        //1.Collection系列集合 Stream()串行和parallelStream()并行
        List list = new ArrayList<>();
        Stream stream = list.stream();
        System.out.println(stream);

        //2.Arrays中的静态方法stream()获取数组流
        Student[] stus = new Student[10];
        Stream stream2 = Arrays.stream(stus);
        System.out.println(stream2);

        //3.Stream类中的静态方法of()
        Stream stream3 = Stream.of("a", "b", "c");
        System.out.println(stream3);

        //4.无限流
        Stream.iterate(0, (x) -> x + 1).limit(10).forEach(System.out::println);
        //5.生成
        Stream.generate(() ->((Math.random())*100)).limit(10).forEach(System.out::println);

    }

输出结果:
java.util.stream.ReferencePipeline$Head@79be0360
java.util.stream.ReferencePipeline$Head@22a67b4
java.util.stream.ReferencePipeline$Head@57855c9a
88
6
55
67
91
17
91
9
6
14

(1)中间操作

(a)filter过滤,相当于sql中where age > 40

forEach(System.out::println)为终止操作,下面只是想看到操作结果
在forEach,其实没做任何操作,当执行到forEach终止操作才执行

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Student {

    private Integer stuId;

    private String name;

    private Integer age;

    private Double matchScore;

    public Student(String name) {
        this.name = name;
    }
}

    /**
     * filter过滤
     */
    @Test
    public void test1() {
        stus.stream().filter(x -> x.getAge() > 40).forEach(System.out::println);
    }
limit截断
    /**
     * limit截断
     */
    @Test
    public void test2(){
        stus.stream().limit(2).forEach(System.out::println);
    }
skip跳过
    /**
     * skip跳过
     */
    @Test
    public void test3(){
        stus.stream().skip(2).forEach(System.out::println);
    }
distinct去重
    /**
     * distinct去重
     */
    @Test
    public void test4() {
        stus.stream().distinct().forEach(System.out::println);
    }

(b)映射

map会转换成一个新对象
    /**
     * map映射
     */
    @Test
    public void test5() {
        List a = Arrays.asList("abc", "cba", "bca");
        a.stream().map(x -> x.toUpperCase()).forEach(System.out::println);

        stus.stream().map(Student::getStuId).forEach(System.out::print);
    }

输出结果为:
ABC
CBA
BCA
112345

flatMap将多个流里元素加到同一个流中
   @Test
    public void test6() {
        List a = Arrays.asList("abc", "cba", "bca");

        Stream> s = a.stream().map(TestLambda4::filterCharacter);
        s.forEach(x -> {
            x.forEach(System.out::println);
        });

        //直接使用flatMap
        Stream s1 =  a.stream().flatMap(TestLambda4::filterCharacter);
        System.out.println("--------------------------");
        s1.forEach(System.out::println);
    }

    public static Stream filterCharacter(String str) {
        List list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

结果输出一样。

(c)排序

    /**
     * 排序
     */
    @Test
    public void test8() {
        List a = Arrays.asList("bb", "cc", "dd", "aa");

        //自然排序(comparable)
        a.stream().sorted().forEach(System.out::println);

        //定制排序()
        stus.stream().sorted((x, y) -> x.getMatchScore().compareTo(y.getMatchScore())).forEach(System.out::println);
    }

(2)终止操作

(a)查找与匹配

获取数据

    @Test
    public void test1() {
        //是否匹配所有元素返回true
        boolean b1 = stus.stream().allMatch(x -> x.getAge() > 19);
        System.out.println(b1);

        //只要有一个匹配返回true
        boolean b2 = stus.stream().anyMatch(x -> x.getAge() > 43);
        System.out.println(b2);

        //没有匹配所有元素(都不符合返回true)
        boolean b3 = stus.stream().noneMatch(x -> x.getAge() > 43);
        System.out.println(b3);

        //取第一条,因为结果可能为空,可以用Optiona接,可以用方法get获取
        Optional op1 = stus.stream().sorted((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())).findFirst();
        System.out.println(op1.get());

        //随机取一条
        Optional op2 = stus.parallelStream().findAny();
        System.out.println(op2.get());
    }

统计,与数据库中的聚合函数类似

    @Test
    public void test2() {
        //相当于sql中count
        Long num1 = stus.stream().count();
        System.out.println(num1);

        //max或者min一样
        Optional op1 = stus.stream().max((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore()));
        System.out.println(op1.get());

        System.out.println(stus.stream().map(Student::getMatchScore).min(Double::compare).get());
    }
(b)归约
  /**
     * 归约
     * reduce(T identy, BinaryOperaator)/reduce(BinaryOperaator)
     * 可以将流中元素反复结合起来,得到一个新的值
     */
    @Test
    public void test3() {
        List lis = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        //算总和
        Integer sum = lis.stream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        /**
         * 统计总分
         * 流行map-reduce模式,大数据里面
         */
        Double sum1 = stus.stream().map(Student::getMatchScore).reduce(Double::sum).get();
        System.out.println(sum1);
    }

(c)收集

    /**
     * collect--将流转换成其他方式。接收一个Collector接口的实现,用于给stream中元素做汇总的方法
     */
    @Test
    public void test4() {
        //
        List lis = stus.stream().map(Student::getName).collect(Collectors.toList());
        lis.forEach(System.out::println);

        HashSet hs = stus.stream().map(Student::getName).collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);

        //会报错 Duplicate key 100.0,
        Map hs2 = stus.stream().collect(Collectors.toMap(Student::getStuId, Student::getMatchScore));
        Map hs1 = stus.stream().collect(Collectors.toMap(Student::getStuId, Function.identity(), (key1, key2) -> key2));
        System.out.println(hs1);
    }
(d)数据库中聚合函数操作
 @Test
    public void test5() {
        //总数
        Long count = stus.stream().collect(Collectors.counting());
        System.out.println(count);

        //平均值
        Double avg = stus.stream().collect(Collectors.averagingDouble(Student::getMatchScore));
        System.out.println(avg);

        //总和
        Double sum = stus.stream().collect(Collectors.summingDouble(Student::getMatchScore));
        System.out.println(sum);

        //最大值
        Optional max = stus.stream().collect(Collectors.maxBy((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())));
        System.out.println(max.get().getMatchScore());

        //最小值
        Optional min = stus.stream().collect(Collectors.minBy((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())));
        System.out.println(min.get().getMatchScore());


        //获取以上所有
        DoubleSummaryStatistics dss = stus.stream().collect(Collectors.summarizingDouble(Student::getMatchScore));

    }

(e)分组,分区以及字符串拼接
   /**
     * 分组
     */
    @Test
    public void test6() {
        //根据年龄分组
        Map> map = stus.stream().collect(Collectors.groupingBy(Student::getAge));
        System.out.println(map);

        //多级分组 先年龄分在按 分数分
        Map>> map1 = stus.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(
                (e) -> {
                    if (e.getMatchScore() > 80) {
                        return "优秀";
                    } else {
                        return "及格";
                    }
                }
        )));
        System.out.println(map1);

        //分区
        Map> map2 = stus.stream().collect(Collectors.partitioningBy(e -> e.getMatchScore() > 80));
        System.out.println(map2);

        //文件拼接,常用于文件的拼接
        String s = stus.stream().map(x -> x.getStuId() + "|" + x.getName()).collect(Collectors.joining("\n", "+++", "---"));
        System.out.println(s);

    }

2.Optional容器类

(1)一个容器类,代表一个值存在或者不存在(null),为了避免控制异常,用起来十分方便。
   @Test
    public void test1() {
        //创建一个Optional实例
        Optional op1 = Optional.of(new Student("2"));
        System.out.println(op1);

        // Optional.of(null); NullPointerException

        //创建一个空对象
        Optional op2 = Optional.empty();
        System.out.println(op2);

        //有值则创建一个Optional实例,无创建一个空对象
        Optional op3 = Optional.ofNullable(null);
        System.out.println(op3);

        //optional 提供了一个方法 isPresent判断是否有值
        if(op3.isPresent()){
            System.out.println(op3);
        }
    }

输出结果:
Optional[Student(stuId=null, name=2, age=null, matchScore=null)]
Optional.empty
Optional.empty

(2)实践应用

常常会遇到如果为null的时候给一个默认值

    @Test
    public void test2() {
        //项目中经常会用到 有则干嘛, 无责干嘛 if else
        Optional op1 = Optional.ofNullable(new String("1"));
        Student st = new Student("test");
        String op = Optional.ofNullable(st.getName()).orElse("@");
        System.out.println(op);

        Optional op2 = Optional.ofNullable(new Student("mayun"));
        Optional op3 = Optional.empty();

        Student s1 = op2.orElseGet(() -> new Student("mahuateng"));
        Student s2 = op3.orElseGet(() -> new Student("mahuateng"));
        System.out.println(s1 + "++++" + s2);
    }

输出结果:
test
Student(stuId=null, name=mayun, age=null, matchScore=null)++++Student(stuId=null, name=mahuateng, age=null, matchScore=null)
欢迎大家一起来补充修正!!!

你可能感兴趣的:(2.java8新特性之Stream)