JAVA 8 新特性之 Lambda 表达式基础语法
前序:
1:Lambda 表达式 及支持 jdk 8 或以上 版本。 2:学习 Lambda 表达式需要了解 “函数式接口”。 3:用过Idea 编辑器的朋友应该知道,idea 已经支持 lambda 表达式,即使你和我一样还不了解 Lambda表达式 ,你若代码中出现了可以更改成Lambda表达式的代码,idea会自动提示你。
4:即便支持就更要学习一下,要不然你会和我一样闹出笑话(真人真事)。
讲个笑话,最开始接触idea(eclipse 转 idea) 的时候,用Runnable 时,idea 出现黄色警告⚠,那是我第一次接触Lamdba 表达式,当时就很好奇跟同事讲 idea 居然可以这样写。现在想起那个同事的表情,就知道他当时为什么不理我了。
Lambda 表达式基础语法总结:
- 语法格式一:无参,无返回值
语法:() -> 具体的实现
演示对象:我们拿 Runable 来演示- 传统代码
/** * 测试 * @param args */ public static void main(String[] args) { Runnable runnable=new Runnable() { @Override public void run() { System.out.println("传统方式 无参,无返回值"); } }; runnable.run(); } // 运行结果 传统方式 无参,无返回值
- Lambda 表达式:有没有眼前一亮,是不是很简单。
/** * 测试 * @param args */ public static void main(String[] args) { Runnable runnable= () -> System.out.println("Lambda 无参,无返回值");
runnable.run(); } //运行结果 Lambda 无参,无返回值
- 传统代码
- 语法格式二:有一个参数,并且无返回值
语法:(x)-> 具体的实现
演示对象:自定义 ”函数式接口“
与上面不同:这里有了一个 x ,x:表示参数,- 自定义一个”函数式接口”
/** * @author Administrator * @version 1.0 * @describe * @date 2019/12/21 20:23 */ @FunctionalInterface public interface FunctionTest { /** * 用于对这个数值 进行处理, * 交由 子类实现。 * @param num */ void calculate(int num); }
- Lambda 表达式实现:这里的 x 表示形参,是calculate方法 传进来的 10,你也可以不取名为x , 其它的都可以。
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中的偶数 FunctionTest test =(x) ->{ for (int i = 0; i < x; i++) { if (i % 2 == 0) { System.out.println(i); } } }; test.calculate(10); } // 运行结果 0 2 4 6 8
- 自定义一个”函数式接口”
- 语法格式三:若有一个参数,小括号省略不写
x -> 具体的实现
演示对象:用 语法格式二 来做演示-
代码演示:忽略 x 的小括号,
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中 2的倍数 FunctionTest test = x ->{ for (int i = 0; i < x; i++) { if (i % 2 == 0) { System.out.println(i); } } }; test.calculate(10); } #运行结果 0 2 4 6 8
-
- 语法格式四:若存在多个参数、多条语句时,那么必须 带 {}。
(x,y) ->{具体的实现}
演示对象:自定义” 函数接口 “,
强调:若存在多个参数时,必须带上"小括号",取什么名无所谓,不重复即可。- 自定义”函数接口“
/** * @author Administrator * @version 1.0 * @describe * @date 2019/12/21 20:23 */ @FunctionalInterface public interface FunctionTest { /** * 用于对两个数值 进行处理, * 交由 子类实现。 * @param num1 * @param num2 */ void calculate(double num1,double num2); }
- 自定义”函数接口“
-
- Lambda 表达式实现方式一:计算两个数的和
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中 2的倍数 FunctionTest test = (x,y) -> System.out.println(String.format("%s + %s = %s",x,y,x+y)); test.calculate(5,3); } // 运行结果 5.0 + 3.0 = 8.0
- Lambda 表达式实现方式二:计算两个数的 积
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中 2的倍数 FunctionTest test = (x,y) -> System.out.println(String.format("%s x %s = %s",x,y,x*y)); test.calculate(4,6); } // 运行结果 4.0 x 6.0 = 24.0
- Lambda表达式实现方式三:上面都是 单条语句的,下面实现多条语句,分别输出两个参数的值就行了。
/** * 测试 * @param args */ public static void main(String[] args) { //需求:打印一个数值中 2的倍数 FunctionTest test = (x,y) ->{ System.out.println(String.format("x = %s",x)); System.out.println(String.format("y = %s",y)); }; test.calculate(4,6); } //运行结果 x = 4.0 y = 6.0
- 传统方式实现:
第一种方式:创建一个子类由子类来实现。 这里就不介绍 第一种方式了,太麻烦还得创建一个新的类。 第二种方式:采用匿名内部类的方式进行实现。 - 采用 匿名内部类的方式进行实现两个数(4 和 5)的和
public static void test(double x,double y,FunctionTest test){ test.calculate(x,y); } /** * 测试 * @param args */ public static void main(String[] args) { //匿名内部类的方式进行实现 test(4, 5, new FunctionTest() { @Override public void calculate(double num1, double num2) { System.out.println(num1* num2); } }); } // 运行结果: 20.0
- Lambda 表达式实现方式一:计算两个数的和
5. 语法格式五:若存在多个参数、单条语句时,return 或 {} 可以省略不写。
-
- 代码上面已经演示过了,但是上面的案例都是无返回值的,那么看看有返回值的情况下是怎么样的
- 更改一下 接口方法。
/** * @author Administrator * @version 1.0 * @describe * @date 2019/12/21 20:23 */ @FunctionalInterface public interface FunctionTest { /** * 用于对这个数值 进行处理, * 交由 子类实现。 * @param num1 * @param num2 */ double calculate(double num1,double num2); }
- 代码演示 有返回值的 Lambda 表达式
/** * 测试 * @param args */ public static void main(String[] args) { FunctionTest test=(x,y) ->{ double result = x * y; return result; }; System.out.println(test.calculate(10,2)); } # 运行结果 20.0
6. 语法格式六:Lambda 表示的参数列表的参数类型可以省略不写,因为JVM编辑器通过上下文推断出,数据类型,即“类型推断”。
JAVA 内置四大核心 函数接口
上面的案例中,每写一个案例,都需要自己创建一个 “函数接口”,在java 中已经为我们内置好了一些“函数接口”,对于一些普通的操作,我们就无需再自己去创建接口。但是面对比较复杂的业务时,还是需要我们自己来创建的。
只要这四大函数接口能充分掌握了,那么其他的也就水到渠成了。
- 四大核心 函数接口 分类
名称 定义 方法 解释 Consumer<T> 消费型接口 void accept(T t); 消费型接口,主要用于做一些无返回值数据处理,最简单的案例就是 在里面输出一句话 System.out.println("hello word!")。 Supplier<T> 供给型接口 T get() 供给型接口,主要是用于提供一些资源响应。如Random.nextInt()方法,它就是产生一些随机数并返回。默默的奉献着,不收取人任何回报。 Function<T,R> 函数型接口 R apply(T t) 函数型接口,有两个参数(T、R),对 T 进行处理,返回 R。 Predicate<T> 断言型接口 boolean test(T t) 主要用于做一些判断型操作。
- Consumer 案例演示
/** * 测试 * @param args */ public static void main(String[] args) { List<Integer> numbers=new ArrayList<>(); numbers.add(52); numbers.add(18); numbers.add(45); numbers.add(12); numbers.add(63); //案例: 将上列数据 按照 升序进行排列 Consumer<List<Integer>> consumer=(t)->{ int size = numbers.size(); for (int i = 0; i < size-1; i++) { for (int j = 0; j < size-1-i; j++) { //比较两个整数的大小 if (numbers.get(j)>numbers.get(j+1)) { Integer temp = numbers.get(j); // 使用list集合的set方法,找到位置并将数字赋值到该位置 numbers.set(j, numbers.get(j+1)); numbers.set(j+1,temp); } } } }; consumer.accept(numbers); for (int i = 0; i < numbers.size(); i++) { System.out.println(numbers.get(i)); } }
- Consumer 案例结果
12 18 45 52 63
- 也可以这样实现。
/** * 测试 * @param args */ public static void main(String[] args) { List<Integer> numbers=new ArrayList<>(); numbers.add(52); numbers.add(18); numbers.add(45); numbers.add(12); numbers.add(63); sort(numbers,(t)->{ int size =numbers.size(); for (int i = 0; i < size-1; i++) { for (int j = 0; j < size-1-i; j++) { //比较两个整数的大小 if (numbers.get(j)>numbers.get(j+1)) { Integer temp = numbers.get(j); // 使用list集合的set方法,找到位置并将数字赋值到该位置 numbers.set(j, numbers.get(j+1)); numbers.set(j+1,temp); } } } }); //打印 排序后的结果 System.out.println(numbers); } // 自定义方法,这样的方式会更加灵活, public static void sort(List<Integer> list, Consumer consumer){ consumer.accept(list); }
// 运行结果
[12, 18, 45, 52, 63] - Supplier 案例演示:
需求:根据用户输入条件 匹配 用户信息并返回。 如:用户输入 一个 数据 16,那么匹配用户集合中包含 16 的数据信息。并做返回。 定义一个 三条用户数据信息,存放到 集合中。 然后 采用 Supplier 供给型函数接口 实现数据匹配。
/** * 测试 定义一个map list 模拟 用户信息, * @param args */ public static void main(String[] args) { List<Map<String,String>> nameList=new ArrayList<>(); Map<String,String> user1=new HashMap<>(5); user1.put("姓名","张三"); user1.put("年龄","18"); user1.put("性别","男"); nameList.add(user1); Map<String,String> user2=new HashMap<>(5); user2.put("姓名","春丽"); user2.put("年龄","16"); user2.put("性别","女"); nameList.add(user2); Map<String,String> user3=new HashMap<>(5); user3.put("姓名","小明"); user3.put("年龄","16"); user3.put("性别","男"); nameList.add(user3); //根据 数据为16 的用户信息 List< Map<String,String>> maps= queryUserName( nameList,()->"16"); System.out.println(maps); } /** * 根据用户输入条件,匹配用户信息并返回 * @param mapList * @param supplier * @return */ public static List< Map<String,String>> queryUserName( List<Map<String,String>> mapList,Supplier<String> supplier){ List< Map<String,String>> mapList1=new ArrayList<>(); for (int i = 0; i < mapList.size(); i++) { Map<String,String> map=mapList.get(i); for (String key: map.keySet()){ if (map.get(key).equals(supplier.get())) { mapList1.add(map); continue; } } } return mapList1; }
- Supplier 案例 运行结果:
//包含 16 的数据 有 两条 [{姓名=春丽, 年龄=16, 性别=女}, {姓名=小明, 年龄=16, 性别=男}]
- 若上面的案例太复杂,可以简单的使用 Supplier :实际上在工作中,肯定不会这么写(如下),业务肯定这个复杂,一个复杂 一个简单的对比,只是想说明 supplier 的作用。更想说明 Lambda 表达式的好处。
/** * 测试 * @param args */ public static void main(String[] args) { //生成一个 随机数 Supplier supplier =() -> new Random().nextInt(); System.out.println(supplier.get()); } // 运行结果 1144876318
- Function 案例展示:
需求:对字符串进行处理。
/** * 测试 * @param args */ public static void main(String[] args) { //小写处理 String toLowerCase = strHandler("Hello, Word!",(t)-> t.toLowerCase() ); System.out.println(toLowerCase); //大写处理 String toUpperCase = strHandler("Hello, Word!",(t)-> t.toUpperCase() ); System.out.println(toUpperCase); } /** * 对字符串进行处理 * @param str * @param function * @return */ public static String strHandler(String str, Function<String,String> function){ return function.apply(str); }
- Function 案例 运行结果:
hello, word! HELLO, WORD! - Predicate 案例展示:
检测 用户是否输入的是数字
- 实现代码
/** * 测试 * @param args */ public static void main(String[] args) { // 测试数据 String str= "12"; boolean bool= numberVerification(str,(s)->{ Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$"); Matcher isNum = pattern.matcher(s); if (!isNum.matches()) { return false; } return true; }); System.out.println(bool); } /** * 检测用户输入是否为数字 * @param str * @param predicate * @return */ public static boolean numberVerification(String str, Predicate<String> predicate){ return predicate.test(str); }
- Predicate 案例运行结果:
true
最后总结:
说实话,我案例表述的不是很明白,若你想要好好的学习一下 Lambda 表达式 建议 去 B站 找视频系统学习。以上案例 都是我看视频时,练手用的代码。至于质量而已,我能明白就行了,我又不是行业大佬,也没想过能写出高质量博客,只是记录一下我的学习过程罢了。
你看了,有所感悟,我也很高兴,若是没有帮助,关掉就行了。
后续更新中....

浙公网安备 33010602011771号