Lambda表达式和流式编程
1.lambda表达式
1.无参无返回值
package com.zhang.lambda;
public interface Demo01 {
void method();
/**
* java8之后接口中支持添加非抽象方法和变量
* 在JDK 1.8版本之后允许在接口中定义非抽象的静态方法,也可以出现静态常量。比如我们可以把一些通用的,
* 工具性的东西直接定义在其中
*
* @param args
*/
public static void main(String[] args) {
Demo01 demo = () -> {
System.out.println("lambda无参无返回值,一条语句");
};
demo.method();
Demo01 demo1 = () -> System.out.println("lambda无参无返回值,一条语句时{}可省略");
demo1.method();
int n = 5;//默认被fianl修饰
Demo01 demo2 = () -> {
System.out.println("lambda无参无返回值,多条语句时{}不可省略");
// n++; //n默认被fianl修饰,不可改变
System.out.println(n);
};
demo2.method();
}
}
运行结果:
lambda无参无返回值,一条语句
lambda无参无返回值,一条语句时{}可省略
lambda无参无返回值,多条语句时{}不可省略
5
Process finished with exit code 0
注意
- lambda表达式的语句体只有一条时,可以省略{},多条时不可省略
- lambda表达式只能引用被final修饰的外层局部变量
2.有一个参数无返回值
package com.zhang.lambda;
public interface Demo02 {
void method(int num);
public static void main(String[] args) {
Demo02 demo = (int num) -> {
System.out.println(num);
};
demo.method(200);
//参数类型可以省略,参数可以随便定义
Demo02 demo1 = (n) -> {
System.out.println(n + 100);
};
demo1.method(300);
//一个参数时,()可以省略,一条语句时,可以省略{}
Demo02 demo2 = n -> System.out.println(n + 100);
demo2.method(300);
//多条语句时,不可以省略{}
int m = 3;
Demo02 demo3 = n -> {
System.out.println(n + 100);
System.out.println(m);
};
demo3.method(300);
}
}
运行结果:
200
400
400
400
3
注意
- lambda表达式只有一个参数时,参数类型可以省略,参数名可以是任意名称
- lambda表达式只有一个参数时,参数外的()可以省略
3.多个参数无返回值
package com.zhang.lambda;
public interface Demo03 {
void method(int num, String name);
public static void main(String[] args) {
//多个参数时,参数类型可以省略,()不可省略
Demo03 demo = (n, str) -> {
System.out.println(n + "===" + str);
System.out.println("多个参数");
};
demo.method(100, "test");
}
}
运行结果:
100===test
多个参数
注意:
lambda表达式有多个参数时,参数外的()不可省略
4.有参数有返回值
package com.zhang.lambda;
public interface Demo04 {
int method(int num);
public static void main(String[] args) {
Demo04 demo = (n) -> {
return n;
};
System.out.println(demo.method(100));
//单行语句可省略{}和return
Demo04 demo1 = (n) -> n;
System.out.println(demo1.method(100));
}
}
运行结果:
100
100
注意:
-
有返回值的lambda表达式,如果方法体只有一条语句,可以同时省略{}和return
-
虽然lambda表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以用lambda表达式来实现。
lambda规定接口中只能有一个需要被实现的抽象方法,不是规定接口中只能有一个方法,称为函数式接口
总结:
->左边:
- 参数类型可以不写
- 如果只有一个参数,()可以省略
->右边:
- {}将方法体的具体内容包裹起来
- 方法体只有一条语句时,{}可以省略不写
- 方法体只有一条语句,且有返回值时,{}和return可以省略不写
2.函数式接口
-
接口类上加@FunctionalInterface注解的是函数式接口
-
函数式接口只能有一个抽象方法,其他的可以有default,static,Object里的public方法等
-
作用:在java中主要用在lambda表达式上
-
Comparator,Runnable,Callable都是函数式接口(注意:Comparable并没有被标记为函数式接口)
代码示例:
package com.zhang.func;
@FunctionalInterface
public interface Demo01 {
//抽象方法
void method();
//静态方法
public static void main(String[] args) {
}
//静态方法
static void method1() {
}
//default修饰的方法
default void method2() {
}
//object里面的public方法
public boolean equals(Object obj);
}
内置函数式接口
- 使lambda表达式的运用方便
- 主要有以下四类
1.消费型接口
代码示例1(遍历list):
package com.zhang.func;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class FunInterface {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 54, 36);
System.out.println(list);
//匿名内部类遍历
Consumer consumer = new Consumer<Integer>() {
@Override
public void accept(Integer o) {
System.out.println(o);//o就是list中的元素
}
};
list.forEach(consumer);
//lambda表达式遍历
list.forEach((elem) -> {
System.out.println(elem);
});
}
}
运行结果:
[10, 40, 20, 40, 30, 54, 36]
10
40
20
40
30
54
36
10
40
20
40
30
54
36
Process finished with exit code 0
代码示例2(遍历map):
package com.zhang.func;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class FunInterface1 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("cn", "China");
map.put("jp", "Japan");
map.put("us", "the United States");
map.put("us", "America");
map.put("uk", "England");
map.put("en", "England");
//匿名内部类遍历
BiConsumer biConsumer = new BiConsumer<String, String>() {
@Override
public void accept(String o, String o2) {
System.out.println(o+"------>"+o2);
}
};
map.forEach(biConsumer);
//lambda表达式遍历
map.forEach((o,o2)-> System.out.println(o+"--->"+o2));
}
}
运行结果:
jp------>Japan
uk------>England
en------>England
cn------>China
us------>America
jp--->Japan
uk--->England
en--->England
cn--->China
us--->America
Process finished with exit code 0
2.断言型接口
代码示例1:
package com.zhang.func;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* 删除成绩小于60的
*/
public class FunInterface3 {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 60, 80, 70);
//匿名内部类
Predicate predicate = new Predicate<Integer>() {
@Override
public boolean test(Integer o) {
if (o < 60) {
return true;
}
return false;
}
};
list.removeIf(predicate);
System.out.println(list);
List<Integer> list2 = new ArrayList();
Collections.addAll(list2, 10, 40, 20, 40, 30, 60, 80, 70);
//lambda表达式
list2.removeIf(elem -> {
if (elem < 60) return true;
return false;
});
System.out.println(list2);
}
}
[60, 80, 70]
[60, 80, 70]
Process finished with exit code 0
代码示例2:
package com.zhang.func;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* 保留成绩小于60的
*/
public class FunInterface4 {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 60, 80, 70);
list = retainIf((elem) -> {
if (elem < 60) return true;
return false;
}, list);
System.out.println(list);//[10, 40, 20, 40, 30]
}
public static List retainIf(Predicate<Integer> predicate, List<Integer> list) {
List list2 = new ArrayList();
for (int i = 0; i < list.size(); i++) {
int elem = list.get(i);
if (predicate.test(elem)) {
list2.add(elem);
}
}
return list2;
}
}
3.方法引用
当lambda表达式的方法体仅仅调用一个已经存在的方法,而不做任何其他的操作,对于这种情况,可以通过一个方法名来引用已经存在的方法,属于简化版的lambda表达式
方法引用的操作符是双冒号::
代码示例1:
package com.zhang.method;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.w3c.dom.ls.LSOutput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class MethDemo01 {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 54, 36);
//匿名内部类遍历
Consumer consumer = new Consumer<Integer>() {
@Override
public void accept(Integer o) {
System.out.println(o);//o就是list中的元素
}
};
list.forEach(consumer);
//lambda表达式遍历
list.forEach((elem) -> {
System.out.println(elem);
});
System.out.println("========简化========");
//简化为方法引用:
list.forEach(System.out::println);//对象引用::实例方法名
}
}
代码示例2:
package com.zhang.method;
import java.util.function.Supplier;
public class MethDemo02 {
public static void main(String[] args) {
Student student = new Student(1, "zhangsan", 89.0, 23);
//供给型函数
//匿名内部类
Supplier supplier = new Supplier<String>() {
@Override
public String get() {
return student.getName();
}
};
System.out.println(supplier.get());
//lambda表达式
Supplier supplier1 = () -> student.getName();
System.out.println(supplier1.get());
System.out.println("======简化=====");
Supplier supplier2 = student::getName;//对象引用::实例方法名
System.out.println(supplier2.get());
}
}
zhangsan
zhangsan
======简化=====
zhangsan
代码示例3:
package com.zhang.method;
import java.util.Comparator;
public class MethDemo03 {
public static void main(String[] args) {
//匿名内部类
Comparator comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// return o1 - o2;
return Integer.compare(o1, o2);
}
};
System.out.println(comparator.compare(10, 20));
//lambda表达式
Comparator<Integer> comparator1 = (o1, o2) -> {
return Integer.compare(o1, o2);
};
System.out.println(comparator1.compare(40, 30));
System.out.println("==============简化============");
Comparator<Integer> comparator2 = Integer::compare;//类名::静态方法名
System.out.println(comparator2.compare(40, 30));
}
}
-1
1
==============简化============
1
4.流式编程
1. 流式编程(Stream)是专门针对集合的一系列操作,与lambda表达式相结合时,极大的精减了代码,提高了编程效率
2.Stream的三个操作步骤:
第一步:创建Stream:从一个数据源,如从集合或数组中获取流
第二步:中间操作:对数据源的数据进行各种中间操作
第三步:终止操作:执行中间操作,并产生结果
代码示例1(中间操作和终止操作):
package com.zhang.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class StreamDemo01 {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 60, 98, 87, 74, 98);
//第一步:创建流
Stream<Integer> stream = list.stream();
//第二步:各种中间操作 filter过滤 ;distinct 去重;sorted排序,默认升序,通过实现比较器来降序排列;
//skip跳过;map 函数式编程 每个-5分
stream = stream.filter((item) -> {
if (item > 60) return true;
return false;
}).distinct()
.sorted((x1, x2) -> x2 - x1)
.skip(1)
.map(x -> x - 5);
//第三步:终止操作
//stream.forEach(System.out::println);// 82 69
System.out.println(stream.count());//2
//System.out.println(stream.max((x1,x2)->{return x1-x2;}));//Optional[82]
}
}
代码示例2(创建stream):
package com.zhang.stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamDemo02 {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
Collections.addAll(list, 10, 40, 20, 40, 30, 60, 98, 87, 74, 98);
System.out.println("========创建流,方法一 list.stream()===========");
Stream<Integer> stream = list.stream();
stream.forEach(System.out::println);
System.out.println("========创建流,方法二 list.parallelStream(),并行流,速度快,顺序不确定===========");
Stream<Integer> stream2 = list.parallelStream();
stream2.forEach(System.out::println);
System.out.println("========创建流,方法三 Stream.of() 直接传数值===========");
Stream<Integer> stream3 = Stream.of(10, 40, 20, 40, 30, 60, 98, 87, 74, 98);
stream3.forEach(System.out::println);
System.out.println("========创建流,方法四 Arrays.stream() ====IntStream=======");
int[] arr = {10, 40, 20, 40, 30, 60, 98, 87, 74, 98};
IntStream stream4 = Arrays.stream(arr);
stream4.forEach(System.out::println);
System.out.println("========创建流,方法五 Stream.generate() 供给型函数=======");
Stream<Double> stream5 = Stream.generate(() -> Math.random());
stream5.limit(10).forEach(System.out::println);
System.out.println("========创建流,方法六 Stream.iterate()=======");
/*UnaryOperator unaryOperator=new UnaryOperator<Integer>() {
@Override
public Integer apply(Integer o) {
return o+1;
}
};
Stream stream6 = Stream.iterate(10, unaryOperator);*/
Stream stream6 = Stream.iterate(10, n->n+1);
stream6.limit(10).forEach(System.out::println);
}
}
========创建流,方法一 list.stream()===========
10
40
20
40
30
60
98
87
74
98
========创建流,方法二 list.parallelStream(),并行流,速度快,顺序不确定===========
98
60
74
98
87
20
40
10
30
40
========创建流,方法三 Stream.of() 直接传数值===========
10
40
20
40
30
60
98
87
74
98
========创建流,方法四 Arrays.stream() ====IntStream=======
10
40
20
40
30
60
98
87
74
98
========创建流,方法五 Stream.generate() 供给型函数=======
0.7431622730319491
0.43443161309550227
0.8645667709688453
0.6877686922162565
0.6140667710241576
0.6693309354076292
0.31653464589793023
0.05020886948639036
0.9681932539200534
0.5413376067167883
========创建流,方法六 Stream.iterate()=======
10
11
12
13
14
15
16
17
18
19
Process finished with exit code 0