Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正在将自己变的更高(Sha)级(Gua),更人性化。————可以这么说lambda表达式其实就是实现SAM接口的语法糖。
Lambda语法 Lambda的语法极为简单,类似如下结构: (parameters) -> expression
或者 (parameters) -> { statements; }
Lambda表达式由三部分组成:
paramaters :类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断1。另外当只有一个推断类型时可以省略掉圆括号。
-> :可理解为“被用于”的意思
方法体 :可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ()->10 (int x,int y)->x+y; (x,y)->x+y; (String name)->System.out.println(name); name->System.out.println(name); (String name,String sex)->{System.out.println(name);System.out.println(sex)} x->2 *x
一.匿名函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package lambdaDemo.com.mission;public class FunctionDemo { public int add (int x,int y) { return x+y; } Runnable run1= ()->{System.out.println("run1---------" );}; Runnable run2 =new Runnable() { @Override public void run () { System.out.println("run2---------" ); } }; public static void main (String[] args) { FunctionDemo demo1 =new FunctionDemo(); demo1.run1.run(); demo1.run2.run(); } }
结果1 2 3 4 run1--------- run2--------- Process finished with exit code 0
第一个场景应用 需求:任意2个数的计算
案例: 例一: 方法add(1,2)=1+2=3 例二: 方法mult(1,2)=1*2=2
以前写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package lambdaDemo.com.mission;public interface Calc { public int add (int x,int y) ; public int mult (int x,int y) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package lambdaDemo.com.mission;public class Calcimpl implements Calc { @Override public int add (int x, int y) { return x+y; } @Override public int mult (int x, int y) { return x*y; } }
lambda写法 1 2 3 4 5 6 7 8 9 10 11 12 package lambdaDemo.com.mission;@FunctionalInterface public interface LambaCalc { public int calc (int x,int y) ; }
调用方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package lambdaDemo.com.mission;public class Main { public static void main (String[] args) { Calc calc=new Calcimpl(); System.out.println(calc.add(3 , 5 )); System.out.println("------------------" ); LambaCalc f1=(x, y)->{return x+y;}; LambaCalc f2=(x, y)->x+y; System.out.println(f1.calc(3 , 1 )); System.out.println("------------------" ); System.out.println(f2.calc(5 , 6 )); } }
结果1 2 3 4 5 6 7 8 ------------------ 4 ------------------ 11 Process finished with exit code 0
二.容器遍历方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package lambdaDemo.com.mission;import org.junit.Test;import java.util.Arrays;import java.util.List;public class FunctionTest { @Test public void testList () { String[] args ={"player1" ,"player2" ,"player3" ,"player4" ,"player5" }; List<String> playerList= Arrays.asList(args); for (String player : playerList) { System.out.println(player); } System.out.println("--------------------------" ); playerList.forEach((player)->{ System.out.println(player); }); System.out.println("--------------------------" ); playerList.forEach((player)-> System.out.println(player) ); } }
结果1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 player1 player2 player3 player4 player5 -------------------------- player1 player2 player3 player4 player5 -------------------------- player1 player2 player3 player4 player5 Process finished with exit code 0
三.容器内容的删除1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Test public void testDeleteList () { String[] args ={"player1" ,"player2" ,"player3" ,"player4" ,"player5" }; List<String> playerList= new ArrayList<>(); for (String player : args) { playerList.add(player); } System.out.println("-------------原来-------------" ); playerList.forEach((player)-> System.out.println(player) ); Iterator<String> it = playerList.iterator(); while (it.hasNext()){ String player=it.next(); if (player.equals("player2" )){ it.remove(); } } playerList.removeIf(new Predicate<String>() { @Override public boolean test (String player) { return player.equals("player3" ); } }); playerList.removeIf((player)->player.equals("player4" )); System.out.println("------------删除后------------" ); playerList.forEach((player)-> System.out.println(player) ); }
效果1 2 3 4 5 6 7 8 9 10 11 -------------原来------------- player1 player2 player3 player4 player5 ------------删除后------------ player1 player5 Process finished with exit code 0
四.集合Stream的操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package lambdaDemo.com.mission;import org.junit.Test;import java.util.Arrays;import java.util.List;public class CollectionStreamTest { @Test public void testStream () { Integer[] nums={1 ,2 ,3 ,null ,4 ,5 ,null ,6 }; List<Integer> list= Arrays.asList(nums); int sum =0 ; for (Integer num : list) { if (num==null ) { continue ; } sum =sum+num; } System.out.println("old sum ->" +sum); sum = list.stream().filter(x->x!=null ).reduce((s,x)->s+x).get(); System.out.println("stream sum ->" +sum); } }
Stream 中主要包含如下几个方法:
方法名 简介
collect(toList())
通过 Stream 生成一个列表
map
将流中的一个值转换成一个新的值
filter
过滤 Stream 中的元素
flatMap
将多个 Stream 连接成一个 Stream
max
求最大值
min
求最小值
reduce
从一组值中生成一个新的值
上面就是 Stream 中包含的几个主要方法,下面逐一对其介绍:
collect(toList()) & filter collect(toList()) 的作用是通过一个 Stream 对象生成 List 对象,案例:
1 2 3 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); List<Integer> result = list.stream().filter((value) -> value > 2 ).collect(toList()); result.forEach((value) -> System.out.print(value));
上面的代码先创建了一个 List 对象并初始化,然后筛选出大于 2 的值,输出。 filter 方法的作用是过滤 Stream 中的元素,filter 方法是一个高阶函数,接收一个函数接口作为参数,此高阶函数返回一个 boolean 值,返回 true 的元素会保留下来; collect(toList()) 方法将 filter 操作返回的 Stream 生成一个 List。
高阶函数:接收或返回一个函数接口的函数称为高阶函数。 函数接口:只包含一个函数的接口成为函数接口。
map map 函数的作用是将流中的一个值转换成一个新的值,举个例子,我们要将一个 List 转换成 List ,那么就可以使用 map 方法,示例代码:
1 2 3 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); List<String> result = list.stream().map(value -> String.format("String:%s" , value)).collect(toList()); result.forEach(System.out::print);
map 方法将 Integer 元素转换成 String 并使用 collect(toList()) 方法生成一个新的 List。
System.out::print 是 (value) -> System.out.print(value) 的简化版写法。
flatMap flatMap:将多个 Stream 连接成一个 Stream,这个怎么理解呢,举个栗子: 首先定义一个 List 对象,将这个对象中的每一个 String 都分割成一个字母并生成一个新的 List 对象,代码:
1 2 3 4 5 6 7 8 9 10 List<String> list = Arrays.asList("abc" , "def" , "ghi" ); List<Character> result = list.stream().flatMap(value -> { char [] chars = value.toCharArray(); Character[] characters = new Character[chars.length]; for (int i = 0 ; i < characters.length; i++){ characters[i] = chars[i]; } return Stream.of(characters); }).collect(toList()); result.forEach(System.out::println);
上面代码先遍历 list ,通过 flatMap 函数将每个 String 元素都生成一个新的 Stream 并将这些 Stream 连接成一个新的 Stream。
max&min 求最大值最小值,这个很好理解了,直接看代码:
1 2 3 4 List<Integer> list = Arrays.asList(0 , 1 , 2 , 3 ); Comparator<Integer> comparator = (o1, o2) -> o1.compareTo(o2); System.out.println(list.stream().min(comparator).get()); System.out.println(list.stream().max(comparator).get());
min 和 max 函数需要一个 Comparator 对象为参数作为比对依据。
reduce 从一组值中生成一个新的值,reduce 函数其实用途非常广泛,作用也比较大,我们举一个累加的例子:
1 2 3 List<Integer> list = Arrays.asList(0 , 1 , 2 , 3 ); int count = list.stream().reduce(0 , (acc, item) -> acc + item).intValue();System.out.println(count);
reduce 函数的一个参数为循环的初始值,这里计算累加时初始值为 0,acc 代表已经计算的结果,item 表示循环的每个元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Test public void testCase () { String[] str ={"test" ,"hello" ,"world" ,"java" ,"tom" ,"C" ,"javascript" }; List<String> list=Arrays.asList(str); list.stream().map(x->x.toUpperCase()).forEach(x-> System.out.println(x)); } @Test public void testTwoFold () { Integer[] data ={1 ,2 ,3 ,4 }; List<Integer> list=Arrays.asList(data); list.stream().map(x->2 *x).forEach(x->System.out.println(x)); } @Test public void testSum () { Integer[] data ={1 ,2 ,3 ,4 }; List<Integer> list =Arrays.asList(data); int num =list.stream().reduce((sum,x)->sum+x).get(); System.out.println(num); }
结果1 2 3 4 5 6 7 TEST HELLO WORLD JAVA TOM C JAVASCRIPT
map和reduce总结
map是针对每个数据处理
reduce是针对集合最后处理
map()进行数据重写组合
reduce()是对集合中所有数据变为一个结果
五.Function函数使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Test public void testConvert () { Function<Integer,String> fun1 =new Function<Integer, String>() { @Override public String apply (Integer integer) { return String.valueOf(integer); } }; String s1=fun1.apply(100 ); System.out.println(s1); Function<Integer,String> fun2=x->String.valueOf(x); String s2=fun2.apply(2 ); System.out.println(s2); }
结果1 2 3 4 100 2 Process finished with exit code 0
六.Consumer用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Test public void testForEach () { String[] str={"A1" ,"B2" ,"C3" ,"D4" }; List<String> list= Arrays.asList(str); list.forEach(new Consumer<String>() { @Override public void accept (String s) { System.out.println(s); } }); System.out.println("----------------------------" ); list.forEach((x)-> System.out.println(x)); }
效果:1 2 3 4 5 6 7 8 9 10 11 A1 B2 C3 D4 ---------------------------- A1 B2 C3 D4 Process finished with exit code 0
七.Predicte用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Test public void testFitler () { String[] str={"A1" ,"B2" ,"C3" ,"D4" }; List<String> list= Arrays.asList(str); list.stream().filter(new Predicate<String>() { @Override public boolean test (String s) { return !s.equals("C3" ); } }).forEach(t-> System.out.println(t)); System.out.println("----------------------------" ); list.stream().filter(x->!x.equals("D4" )).forEach(x-> System.out.println(x)); }
效果:1 2 3 4 5 6 7 8 9 A1 B2 D4 ---------------------------- A1 B2 C3 Process finished with exit code 0
本文到此结束