java 8 函数式编程

读了《java 8函数式编程》,总结一下其中的常用方法,方便平常使用;

目录

函数式编程

Lambda表达式

Stream-流

1、惰性求值 VS. 及早求值

2、常用的流操作

Optional

其他


函数式编程

  • 其核心是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值;

  • 面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象;

Lambda表达式

  • 是一个匿名方法,将行为像数据一样进行传递;

  • 其类型依赖于上下文环境,是由编译器推断出来的;

  • 常见结构:BinaryOperator<Integer> add = (x, y) -> x + y;

Stream-流

  • Stream是用函数式编程方式在集合类上进行复杂操作的工具,是一种内部迭代方式;

  • 通过Stream暴露集合的最大优点在于,它很好的封装了内部实现的数据结构。仅暴露了一个Stream接口,用户在实际操作中无论如何使用,都不会影响内部的List或Set;

1、惰性求值 VS. 及早求值

惰性求值方法:返回值是Stream,没有产生新的集合;

及早求值方法:最终会从Stream产生值,返回的是另一个值或为空;

2、常用的流操作

        //of:使用一组初始值生成新的Stream;
        //collect(Collectors.toList()):由Stream里的值生成一个列表,是一个及早求值操作;
        List<String> list1 = Stream.of("a", "b", "hello")
                .collect(Collectors.toList());
        assert list1.equals(Arrays.asList("a", "b", "hello"));
        //collect(Collectors.toSet()):由Stream里的值生成一个set
        Set<String> set1 = Stream.of("a", "hello", "a")
                .collect(Collectors.toSet());
        //返回值:[a, hello]

        //map:将一种类型的值转化成另外一种类型,从而实现将一个流中的值转化成一个新的流;
        List<String> list2 = Stream.of("a", "b", "hello")
                .map(e -> e.toUpperCase())
                .collect(Collectors.toList());
        assert list2.equals(Arrays.asList("A", "B", "HELLO"));

        //filter:和if条件语句的功能相同,过滤掉不符合条件的,保留符合条件的;
        List<String> list3 = Stream.of("c", "hello")
                .filter(e -> e.length() > 1)
                .collect(Collectors.toList());
        assert list3.equals(Arrays.asList("hello"));

        Student s1 = new Student();
        s1.setGrade(1);
        s1.setAge(17);
        s1.setName("zhangsan");
        s1.setScores(Arrays.asList(88, 77));

        Student s2 = new Student();
        s2.setGrade(1);
        s2.setAge(18);
        s2.setName("lisi");
        s2.setScores(Arrays.asList(67, 78));

        Student s3 = new Student();
        s3.setGrade(2);
        s3.setAge(16);
        s3.setName("wangwu");
        s3.setScores(Arrays.asList(80, 90));

        List<Student> students = new ArrayList<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);

        //flatMap:将多个Stream连接成一个Stream,而不是一连串的流;
        List<Integer> scoreList = students.stream()
                .flatMap(student -> student.getScores().stream())
                .collect(Collectors.toList());
        assert scoreList.equals(Arrays.asList(88, 77, 67, 78, 80, 90));

        //max & min: 求最大值/最小值,需要传递一个Comparator对象,实现静态方法comparing,从而实现一个比较器;
        int max = Stream.of(1, 2, 3).max(Comparator.comparing(e -> e)).get();
        //max = Stream.of(1, 2, 3).mapToInt(e -> e).max().getAsInt();
        assert max == 3;

        Student min = students.stream()
                .max(Comparator.comparing(e -> e.getAge()))
                .get();
        //int min = students.stream().mapToInt(e -> e.getAge()).min().getAsInt();
        assert min.getAge() == 16;

        //count: 计数
        long count = Stream.of(Arrays.asList(1, 2, 3)).count();
        assert count == 3;

        //排序:正序Collections.sort(scoreList),倒序Collections.reverse(ascList);;
        List<Integer> ascList = scoreList.stream()
                .sorted()
                .collect(Collectors.toList());
        //求平均值,返回17.0
        double averageAge = students.stream().mapToInt(Student::getAge).average().getAsDouble();
        //averageAge = students.stream().collect(Collectors.averagingInt(Student::getAge));

        //求总和,返回51
        int totalAge = students.stream().mapToInt(Student::getAge).sum();
        //totalAge = students.stream().collect(Collectors.summingInt(Student::getAge));

        //数据分块,返回{false=[1, 2], true=[3, 4]}
        Map<Boolean, List<Integer>> map1 = Stream.of(1, 3, 4, 2)
                .collect(Collectors.partitioningBy(e -> e > 2));
        //数据分组,返回{1=[java8.Student@3f91beef, java8.Student@1a6c5a9e], 2=[java8.Student@37bba400]}
        Map<Integer, List<Student>> map2 = students.stream()
                .collect(Collectors.groupingBy(e -> e.getGrade()));
        //字符串连接,返回[11,aa,22]
        String result = Stream.of("11", "aa", "22").collect(Collectors.joining(",", "[", "]"));
        //返回11,aa,22
        result = Stream.of("11", "aa", "22").collect(Collectors.joining(","));
        //list转map(key值为姓名)
        Map<String, Student> studentMap = students.stream().collect(Collectors.toMap(e -> e.getName(), e -> e));

Optional

  • 为核心类库新设计的一种数据类型,用来替代null值(使用null代表值不存在的最大问题在于npe);

  • 使用Optional对象的两个目的:

    a、Optional对象鼓励程序员适时检查变量是否为空,以避免代码缺陷;

    b、它将一个类的API中可能为空的值文档话,这笔交易实现代码要简单很多;

  • 在一个值可能为空的建模情况下,使用Optional对象能替代使用null值;

其他

并发 VS. 并行

并发:两个任务共享时间段。如果一个程序要运行两个任务,并且只有一个CPU给他们分配了不同的时间片,这就是并发;

并行:两个任务在同一时间发生,比如运行在多核CPU上;

猜你喜欢

转载自blog.csdn.net/lydia_cmy/article/details/103202143