1 编程范式
主要的编程范式有三种:命令式编程,声明式编程和函数式编程。
1.1 命令式编程
关注计算机执行的步骤,就是告诉计算机先做什么后做什么
1.2 声明式编程
表达程序的执行逻辑,就是告诉计算机要做什么,不指定具体怎么做
1.3 函数式编程
跟声明式编程类似,就是告诉计算机做什么,不指定具体怎么做
1.4 demo实例
1.4.1 需求
随机产生一个int类型的数组,分别利用命令式编程和函数值编程获取数组中的最小值
1.4.2 思路
命令式编程:
随记产生int类型数组 -> 定义一个int类型变量minNumber并取int的最大值 -> 利用循环遍历数组 -> 将数组中的每个元素和minNumber进行比较,如果比minNumber小就复制给minNumber,否则就进行下一次循环
函数值编程:
随记产生int类型数组 -> 定义一个int类型的变量minNumber并取int的最大值 -> 将数组转化成流 -> 调用的流的相关方法获取流中的最小值 -> 将获取到的最小值进行类型转化后在复制给minNumber
1.4.3 代码实现
package a_test_demo; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.Random; import java.util.stream.IntStream; /** * @author 王杨帅 * @create 2018-06-24 17:14 * @desc **/ public class Case02 { /** * 需求:随机产生一个int类型的数组并通过命令式编程和函数式编程分别求出数组中的最小值 */ private int[] nums; // 定义一个int类型的数组 int count = 10; // 数组长度 Random random; // 随机数对象 @Before public void init() { random = new Random(); // 实例化Random nums = new int[count]; // 实例化数组 for (int i = 0; i < nums.length; i++) { // 修改数组内容 nums[i] = random.nextInt(30); } // System.out.println(Arrays.toString(nums)); // 打印数组信息【测试用】 } /** * 利用命令式编程实现 */ @Test public void test01() { int minNumber = Integer.MAX_VALUE; // 存储最小值【初始化时时最大值】 for (int i = 0; i < nums.length; i++) { if (minNumber > nums[i]) { minNumber = nums[i]; } } System.out.println(Arrays.toString(nums) + " 中的最小值为: " + minNumber); } /** * 利用函数式编程实现 */ @Test public void test02() { int minNumber = Integer.MAX_VALUE; minNumber = IntStream .of(nums) // 将数组转化成流 .parallel() // 设置并行处理【PS: 如果是命令式编程需要自己实现相应逻辑】 .min() // 获取流中的最小值 .getAsInt(); // 将值转化成int类型 System.out.println(Arrays.toString(nums) + " 中的最小值为: " + minNumber); } }
2 lambda表达式与匿名内部类
2.1 需求
现有一个名为getName的方法,该方法的参数是一个Student接口;怎么调用getName方法
2.2 思路
2.2.1 思路一
创建一个名为StudentImpl的类,该类实现了Student接口 -> 调用getName方法时传入StudentImpl的实例即可
2.2.2 思路二
利用匿名内部类作为getName方法的实参
2.2.3 思路三
利用lambda表达式作为getName方法的实参
2.3 代码实现
package a_test_demo; import org.junit.Test; public class Case01 { /** * getName方法:用户打印学生的姓名 * @param student Student接口 */ public void getName(Student student) { System.out.println("学生的姓名为:" + student.name()); } /** * 利用实现类实现 */ @Test public void test01() { Student student = new StudentImpl(); getName(student); } /** * 利用匿名内部类实现 */ @Test public void test02() { getName(new Student() { @Override public String name() { return "fury"; } }); } /** * 利用lambda表达式实现 */ @Test public void test03() { getName(() -> "zeus"); } } /** * Student接口 */ interface Student { /** * 抽象方法:返回String类型的姓名 * @return */ String name(); } /** * Student接口的实现类 */ class StudentImpl implements Student { @Override public String name() { return "warrior"; } }
2.4 三种方法使用场景
2.4.1 实现类
当某个类需要实例化多次时使用
2.4.2 匿名内部类
某个类只需要实例化一次而且不需要知道实例名称时使用【通常这个类需要进行重写的方法不止一个】;如果需要知道实例名称时就需要使用内部类
2.4.3 lambda表达式
某个类需要实例化一次而且不需要知道实例名字【这个类中通常有且只有一个需要重写的方法】
2.5 为什么Lambda表达式可以作为方法的参数呢
Lambda 可以作为方法的参数。Lambda 表达式是函数式接口实现类的实例,所以,Lambda 表达式作为方法的参数,实际就是把一个类实例作为方法的参数。Lambda 表达式表达或是设计了一组功能,把它传递给方法作为参数,实际上,可以理解为把一组功能传递给了方法。因此,为了让代码更加简洁,编程更加高效,调用方法(该方法的参数类型是接口类型)时,若接口有多个抽象方法,我们可以创建这个接口的匿名实现类的实例,作为方法的参数。若是接口只有唯一一个抽象方法,比如函数式接口,我们可以创建这个接口的 Lambda 表达式,作为调用方法的参数,把一组功能传递给方法。
技巧01:lambda表达式 “->” 左边相当于函数式接口中那个方法的形参,“->” 的右边相当于函数式接口中那个方法的返回值
技巧02:函数式接口就是只有一个抽象方法的接口
3 lambda表达式的写法
原文地址:https://www.cnblogs.com/NeverCtrl-C/p/9221300.html