Java 8 函数式编程

为什么要引入函数式编程

  • 处理大型数据集合时,Java还欠缺高效的并行操作。
  • 函数式编程能让程序员编写出更容易阅读的代码——这种代码更多地表达了业务逻辑的意图,而不是它的实现机制。易读的代码也易于维护、更可靠、更 不容易出错。面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。

Lambda 表达式

What?

一种紧凑的、传递行为的方式。

How?

// no lambda
button.addActionListener(
      new ActionListener() { 
            public void actionPerformed(ActionEvent event) {
                  System.out.println("button clicked"); 
            }
});
// lambda
button.addActionListener(event -> System.out.println("button clicked"));

函数接口

使用只有一个方法的接口来表示某特定方法并反复使用,这种接口称为函数接口。(我的理解是这种接口只有一种行为,所以可以使用lambda表达式表示这个接口的具体行为。)
例如使用 Swing 编写过用户界面的人对这种方式都不陌生,代码如下

public interface ActionListener extends EventListener { 
      public void actionPerformed(ActionEvent event);
}

Java中重要的函数接口

接口 参数 返回类型 示例
Predicate T boolean 这张唱片已经发行了吗
Consumer T void 输出一个值
Function<T,R> T R 获得 Artist 对象的名字
Supplier None T 工厂方法
UnaryOperator T T 逻辑非(!)
BinaryOperator (T,T) T 求两个数的乘积(*)
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * author: zheng.hong
 * date: 2020/10/29
 * description: Java lambda 表达练习
 */
public class Java8Lamda {
    public static void main(String[] args) {
        
        //Function 接受一个入参T,返回R类型对象,使用apply方法获取方法执行的内容
        Function<User, String> uft = u -> u.getUserName() ;
        String userName = uft.apply(new User("mindong"));
        System.out.println(userName);

        //Consumer 接受一个参数T,没有返回值,使用accept方法对参数执行操作
        Consumer<User> uc = u -> System.out.println(u.getUserName());
        uc.accept(new User("liliang"));

        //Supplier 没有入参,返回T类型结果,使用get方法获取返回结果
        Supplier<User> us = () -> new User( "us");
        User user = us.get();

        //接受一个入参,返回结果为true或者false,使用test方法进行测试并返回测试结果
        Predicate<User> predicate = u -> !u.getUserName().isEmpty();
        System.out.println(predicate.test(user));
        
    }

    private static class User{

        public User(String userName) {
            this.userName = userName;
        }

        private String userName;

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }
    }
}

Stream 流

常用的 Stream 流操作

collection(toList())

map

//对每个元素做平方运算
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
List<Integer> integers = integers.stream().map(number -> number*number).collect(Collectors.toList());
integers.forEach(number -> System.out.print(number+","));

filter

//过滤出偶数
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
integers = integers.stream().filter(number -> number%2 == 0).collect(Collectors.toList());
integers.forEach(number -> System.out.print(number+","));

flatMap

map 操作,它可用一个新的值代替 Stream 中的值。但有时,用户希望让 map 操作有点变化,生成一个新的 Stream 对象取而代之。

// 合并List
List<Integer> together = Stream.of(Arrays.asList(1, 2),Arrays.asList(3, 4)).flatMap(numbers -> numbers.stream())
                .collect(Collectors.toList());

max 和min

//获取集合中最大值
List<Integer> integers = Arrays.asList(1,2,3,4,5,6);
Integer max = integers.stream().max(Comparator.comparing(Integer::intValue)).get();
System.out.println(max);

reduce

//求和
Integer sum = Stream.of(1,2,3).reduce(0,(sum,n)->sum+n );
posted @ 2020-11-03 22:38  Always_July  阅读(118)  评论(0编辑  收藏  举报