本文源码:GitHub·点这里 || GitEE·点这里
一、函数式概念
函数式编程是一种结构化编程的范式,次要思维是把运算过程尽量写成系列嵌套的函数调用。函数编程的概念表述带有很形象的感觉,能够基于案例看:
public class Function01 { public static void main(String[] args) { // 运算:(x+y)* c int x1 = 2 ; int y1 = 3 ; int c1 = 4 ; int sum1 = x1 + y1 ; int res1 = sum1 * c1 ; System.out.println("res1 = "+res1); }}
这里基于过程的形式做计算,下面的代码块着重在形容程序执行过程。
在看基于函数的形式解决办法:
public class Function02 { public static void main(String[] args) { // 函数式计算 System.out.println("func01 = "+func01(2,3,4)); } private static int func01 (int x,int y,int c){ return (x+y)*c; }}
函数式编程的外围因素:传入参数,执行逻辑,返回值,也能够没有返回值。
函数式的编程格调偏重形容程序的执行逻辑,不是执行过程。
同下面计算过程相比,函数式编程也缩小很多长期变量的创立,代码格调也变的简洁分明。
二、函数与办法
在Java语言中有函数式编程格调,然而Java代码中没有函数的说法,而是称为:办法;
public class Function03 { public static void main(String[] args) { Func03 func03 = new Func03(); func03.add(2); System.out.println(func03.res1); }}class Func03 { public int res1 = 0 ; public void add (int a1){ this.res1 = a1 +1 ; }}
类定义援用数据类型,类实例化后的对象能够调用类外部的办法和数据,这是最直观的感觉。
然而办法又有动态和非动态的区别,静态方法属于类所有,类实例化前即可应用。
非静态方法能够拜访类中的任何成员变量和办法,并且必须是类实例化后的对象才能够调用。
三、JDK函数根底
1、Lambda表达式
Lambda表达式也可称为闭包,是推动Java8公布的最重要新个性,容许把函数作为一个办法的参数(函数作为参数传递进办法中)。
这里就很显明的比照Lambda表达式语法和传统用法。
public class Lambda01 { interface LambdaOpera { int operation(int a, int b); } public static void main(String[] args) { LambdaOpera lambdaOpera = new LambdaOpera(){ @Override public int operation(int a, int b) { return a * b ; } }; System.out.println(lambdaOpera.operation(3,2)); LambdaOpera lambdaOpera01 = (int a, int b) -> a + b; LambdaOpera lambdaOpera02 = (int a, int b) -> a - b; System.out.println(lambdaOpera01.operation(3,2)); System.out.println(lambdaOpera02.operation(3,2)); }}
在看一个直观的利用案例,基于Lambda的形式创立线程,能够使代码变的更加简洁紧凑:
public class Lambda02 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 2; i++) { System.out.println(i); } } }).start(); // 比照 Lambda 形式 new Thread(() -> { for (int i = 0; i < 2; i++) { System.out.println(i); } }).start(); }}
在看一下Runnable接口的构造:
FunctionalInterface标记在接口上,示意该接口是函数式接口,并且该接口只蕴含一个形象办法,
@FunctionalInterfacepublic interface Runnable { public abstract void run();}
Lambda表达式自身能够了解为就是一个接口的实现过程,这里runnable就是残缺的Lambda表达式申明:
public class Lambda04 { public static void main(String[] args) { Runnable runnable = () -> { System.out.println("run one..."); }; Thread thread = new Thread(runnable); thread.start(); }}
Lambda表达式最直观的作用就是使得代码变得异样简洁,并且能够作为参数传递。
2、函数式接口
Lambda表达式尽管有很多长处,然而应用的时候须要定义一些接口用来实现编码,这样又使得表达式又变得重量级,Java8本身曾经提供几个常见的函数式接口。
- Function:输出一个参数,返回一个后果;
- Consumer:输出一个参数,不返回后果;
- BiFunction:输出两个参数,返回一个后果;
- BiConsumer:输出两个参数,不返回任何后果;
public class Lambda05 { public static void main(String[] args) { Function<Integer, Integer> function01 = x -> x * 2; System.out.println(function01.apply(2)); BiFunction<Integer, Integer, Integer> function02 = (x, y) -> x * y; System.out.println(function02.apply(2, 3)); Consumer<String> consumer01 = msg -> System.out.println("msg:"+msg); consumer01.accept("hello"); BiConsumer<String,Integer> consumer02 = (msg,i) -> System.out.println(msg+":"+i); consumer02.accept("world",3); }}
如果面对更简单的业务需要,能够自定义函数式接口去解决。
四、Optional类
1、Null判断
Optional类是Java函数式编程的利用,次要用来解决常见的空指针异样问题。
在Java编程的开发中,很多中央都能常见空指针异样的抛出,如果想防止这个问题就要退出很多判断:
public class Optional01 { public static void main(String[] args) { User user = new User(1,"hello") ; if (user != null){ if (user.getName() != null){ System.out.println(user.getName()); } } }}
为了确保程序不抛出空指针这种低级的谬误,在程序中随处能够null的判断,代码显然冗余和繁冗。
2、Optional利用
基于Optional类创立的对象可能蕴含空值和null值,也同样会抛出对应的异样:
public class Optional02 { public static void main(String[] args) { // NoSuchElementException Optional<User> optionalUser = Optional.empty(); optionalUser.get(); // NullPointerException Optional<User> nullOpt = Optional.of(null); nullOpt.get(); }}
所以在不明确对象的具体情况下,应用ofNullable()办法:
public class Optional03 { public static void main(String[] args) { User user = new User(1,"say"); Optional<User> optionalUser = Optional.ofNullable(user); if (optionalUser.isPresent()){ System.out.println(optionalUser.get().getName()); } User user1 = null ; User createUser = Optional.ofNullable(user1).orElse(createUser()); System.out.println(createUser.getName()); User user2 = null ; Optional.ofNullable(user2).orElseThrow( () -> new RuntimeException());; } public static User createUser (){ return new User(2,"hello") ; }}
这样看下来Optional联合链式办法和Lambda表达式就很大水平上简化了利用的代码量:
public class Optional04 { public static void main(String[] args) { // 1、map转换方法 User user = new User(99, "Java"); // user = null ; String name = Optional.ofNullable(user) .map(u -> u.getName()).orElse("c++"); System.out.println(name); // 2、过滤办法 Optional<User> optUser01 = Optional.ofNullable(user) .filter(u -> u.getName() != null && u.getName().contains("c++")); // NoSuchElementException System.out.println(optUser01.get().getName()); }}
Optional提供null解决的各种办法,能够简洁很多代码判断,然而在应用格调上和之前变化很大。
五、Stream流
如果Optional简化很多Null的判断,那Stream流的API则简化了很多汇合的遍历判断,同样也是基于函数式编程。
上述为Stream接口继承关系如图,同样提供一些特定接口和较大的包装接口,通过源码查看,能够看到和函数编程也是密切相关。
public class Stream01 { public static void main(String[] args) { Stream<String> stream = Stream.of("hello", "java"); stream.forEach(str -> System.out.print(str+";")); }}
Stream与函数接口联合应用,函数接口又能够应用Lambda表达式进行简化代码。在Java8通过Stream能够大量简化汇合应用的代码复杂度。
public class Stream02 { public static void main(String[] args) { // 1、转换Stream List<String> list = Arrays.asList("java+;", "c++;", "net;"); list.stream(); // 2、forEach操作 list.stream().forEach(System.out::print); // 3、map映射,输入 3,4 IntStream.rangeClosed(2,3).map(x->x+1).forEach(System.out::println); // 4、filter过滤 list.stream().filter(str -> str.contains("+")).forEach(System.out::print); // 5、distinct去重 Integer[] arr = new Integer[]{3, 1, 3, 1, 2,4}; Stream.of(arr).distinct().forEach(System.out::println); // 6、sorted排序 Stream.of(arr).sorted().forEach(System.out::println); // 7、collect转换 List<String> newList = list.stream().filter(str -> str.contains("+")) .collect(Collectors.toList()); newList.stream().forEach(System.out::print); }}
在没有Stream相干API之前,对于汇合的操作和遍历都会产生大量的代码,通过Stream相干API汇合的函数式编程和Lambda表达式的格调,简化汇合很多操作。
六、源代码地址
GitHub·地址https://github.com/cicadasmile/java-base-parentGitEE·地址https://gitee.com/cicadasmile/java-base-parent
浏览标签
【Java根底】【设计模式】【构造与算法】【Linux零碎】【数据库】
【分布式架构】【微服务】【大数据组件】【SpringBoot进阶】【Spring&Boot根底】
【数据分析】【技术导图】【 职场】