Java8新特性之Lambda表达式
简介
lambda是用来实现接口的一个匿名函数。
( ):用来描述参数列表
{ }:用来描述方法体
-> : lambda运算法,读作goes to
垃圾代码 --> 策略模式 --> 匿名内部类 --> Lambda表达式
接口准备
无参数无返回值
@FunctionalInterface
public interface LambdaNoneReturnNoneParameter {
void test();
}
单个参数无返回值
@FunctionalInterface
public interface LambdaNoneReturnSingleParameter {
void test(int n);
}
多个参无返回值
@FunctionalInterface
public interface LambdaNoneReturnManyParameter {
void test(int n,int b);
}
无参数有返回值
@FunctionalInterface
public interface LambdaSingleReturnNoneParameter {
int test();
}
单个参数有返回值
@FunctionalInterface
public interface LambdaSingleReturnSingleParameter {
int test(int n);
}
多个参数有返回值
@FunctionalInterface
public interface LambdaSingleReturnManyParameter {
int test(int a,int b);
}
基本语法
lambda是实现接口的匿名函数
lambada语法
public class Syntax1 {
public static void main(String[] args) {
//lambda是实现接口的匿名函数
//参数列表 方法体
//无参无返回
//@FunctionalInterface标识接口 只有一个方法
LambdaNoneReturnNoneParameter lambda1 = ()->{
System.out.println("hello world");
};
lambda1.test();
//无返回值,单个参数
LambdaNoneReturnSingleParameter lambda2 = (int a)->{
System.out.println(a);
};
lambda2.test(2);
//无返回值,多个参数
LambdaNoneReturnManyParameter lambda3 = (int a, int b)->{
System.out.println(a+" "+b);
};
lambda3.test(1,2);
//有返回值,无参
LambdaSingleReturnNoneParameter lambda4 = ()->{
System.out.println("lambda4");
return 100;
};
int ret = lambda4.test();
System.out.println(ret);
//有返回值,单个参数
LambdaSingleReturnSingleParameter lambada5 = (int a)->{
System.out.println("lambda5");
return a;
};
int ret2 = lambada5.test(5);
System.out.println(ret2);
LambdaSingleReturnManyParameter lambda6 = (int a,int b)->{
System.out.println("lambda6");
return a+b;
};
int ret3 = lambda6.test(1,2);
}
}
精简语法
public class Syntax2 {
//语法精简
//1. 参数类型
// 要么都省略掉,要么不省略
LambdaNoneReturnManyParameter lambda1 = (a, b)->{
System.out.println("lambda1");
};
//2. 参数列表
// 参数的类型只有一个,此时小括号可以省略
LambdaNoneReturnSingleParameter lambda2 = a ->{
System.out.println("lambda2");
};
//3. 大括号省略
// 方法体中只有一条语句时
LambdaNoneReturnSingleParameter lambda3 = a -> System.out.println("lambda3");
//4. 如果方法体中的唯一语句时返回语句,可以省略return
LambdaSingleReturnNoneParameter lambda4 = () -> 10;
LambdaSingleReturnSingleParameter lambda5 = a -> a;
LambdaSingleReturnManyParameter lambda6 = (a,b)-> a+b;
}
方法引用
public class Syntax3 {
public static void main(String[] args) {
// 方法引用
// 可以快速的将一个lambda表达式的实现指向一个已经实现的方法。
// 语法:方法的隶属者::方法名
// 注意:
// 1. 静态方法 类名::方法名
// 2. 非静态方法: 对象名:方法名
//注意:
//1. 参数数量和类型一定要和接口中定义的方法一致
//2. 返回值得类型和接口中定义方法一致
LambdaSingleReturnSingleParameter lambda1 = a -> change(a);
//方法引用:引用了change方法的实现。
LambdaSingleReturnSingleParameter lambda2 = Syntax3::change;
}
public static int change(int a){
return a*2;
}
}
构造方法引用
public class Syntax4 {
public static void main(String[] args) {
PersonCreater creater1 = ()-> new Person();
//构造方法的引用
PersonCreater creater2 =Person::new;
Person person = creater2.getPerson();
System.out.println(person);
//有参的
PersonCreater2 creater3 = Person::new;
Person person3 = creater3.getPerson2("Jack",18);
System.out.println(person3);
}
// 需求:
interface PersonCreater{
Person getPerson();
}
interface PersonCreater2{
Person getPerson2(String name,int age);
}
}
Person
public class Person {
public String name;
public int age;
public Person() {
System.out.println("无参构造方法");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
集合排序
ArrayList 排序
import java.util.ArrayList;
public class exercise1 {
public static void main(String[] args) {
//集合排序
//ArrayList<>
//需求:一个list中有若干个person,按照年龄降序排序
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("jack",10));
list.add(new Person("lisa",23));
list.add(new Person("jie",23));
list.add(new Person("dd",13));
list.add(new Person("lun",14));
list.add(new Person("shun",12));
list.add(new Person("hao",15));
list.add(new Person("zhu",16));
//排序
list.sort((o1,o2)->{
return o1.age - o2.age;
});
//简化
list.sort((o1,o2)-> o1.age-o2.age);
System.out.println(list);
}
}
TreeSet 排序
import java.util.TreeSet;
public class exercise2 {
public static void main(String[] args) {
// TreeSet 实现降序
// TreeSet<Person> set = new TreeSet<>();
// set.add(new Person("jack",10));
// set.add(new Person("lisa",23));
// set.add(new Person("jie",23));
// set.add(new Person("dd",13));
// set.add(new Person("lun",14));
// set.add(new Person("shun",12));
// set.add(new Person("hao",15));
// set.add(new Person("zhu",16));
// System.out.println(set); 抛出异常,不知道按照哪个元素排序,分不清谁大谁小
//方法一:实现Comparable接口中的方法,自然排序。例如一个数字的集合
//方法二:使用lambada表达式实现Comparator,定制排序。例如一个对象的集合
TreeSet<Person> set2 = new TreeSet<>(((o1, o2) -> o1.age - o2.age));
set2.add(new Person("lisa", 23));
set2.add(new Person("jie", 23));
set2.add(new Person("dd", 13));
set2.add(new Person("lun", 14));
set2.add(new Person("shun", 12));
set2.add(new Person("hao", 15));
set2.add(new Person("zhu", 16));
System.out.println(set2);
//出现相同年龄的只保留一个
//可以重写排序规则
TreeSet<Person> set3 = new TreeSet<>((o1, o2) -> {
if (o1.age >= o2.age){
return -1;
}else {
return 1;
}
});
set3.add(new Person("lisa", 23));
set3.add(new Person("jie", 23));
set3.add(new Person("dd", 13));
set3.add(new Person("lun", 14));
set3.add(new Person("shun", 12));
set3.add(new Person("hao", 15));
set3.add(new Person("zhu", 16));
System.out.println(set3);
}
}
集合的遍历 forEach
import java.util.ArrayList;
import java.util.Collections;
public class exercise3 {
public static void main(String[] args) {
//集合的遍历
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6,7,8,9);
//将集合中的每一个元素都带入到Consumer的accept方法中
list.forEach(System.out::println);
//加入自己的逻辑
list.forEach(ele ->{
if (ele%2 == 0){
System.out.println(ele);
}
});
}
}
集合删除元素 removeif
import java.util.ArrayList;
import java.util.ListIterator;
public class exercise4 {
public static void main(String[] args) {
//需求:删除集合中满足条件的元素
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("jack",10));
list.add(new Person("lisa",23));
list.add(new Person("jie",23));
list.add(new Person("dd",13));
list.add(new Person("lun",14));
list.add(new Person("shun",12));
list.add(new Person("hao",15));
list.add(new Person("zhu",16));
//使用Iterator 删除集合中年两大于15的元素
ListIterator<Person> it = list.listIterator();
while (it.hasNext()){
Person ele = it.next();
if (ele.age>15){
it.remove();
}
}
System.out.println(list);
//使用lambada表达式
//将集合中的每一个元素都带入到Predicate的test方法中,如果返回值是true,则删除这个元素,例子中如果满足年龄大于10的元素则删除
list.removeIf(ele -> ele.age>10 );
System.out.println(list);
}
}
线程实例化
public class exercise5 {
public static void main(String[] args) {
//需求:开辟一个线程,输出数字,开辟一个线程可以通过继承Thread或者实现Runnable接口
//可以使用匿名内部类或者实现Runnable接口
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
t.start();
//使用lambda,Runnable是一个无参无返回的FunctionalInterface接口
Thread t2 = new Thread(()-> System.out.println("hello lambda"));
t2.start();
}
}
系统内置函数式接口
Java内置四大核心函数式接口:
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为T的对象应用操作:void accept(T t) |
Supplier 提供型接口 | 无 | T | 返回类型为T的对象:T get() |
Function<T, R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果为R类型的对象:R apply(T t) |
Predicate 断言型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值:boolean test(T t) |
public class FunctionInterface {
public static void main(String[] args) {
// 系统内置函数式接口
//Predicate<T> : 参数T 返回boolean
// IntPredicate int->boolean
// LongPredicate long->boolean
// DoublePredicate double->boolean
//Consumer<T> : 参数T 返回void
// IntConsumer : int ->void
// LongConsumer : long -> void
// DoubleConsumer : double -> void
//Function<T,R> : 参数T 返回R 指定传入参数指定返回参数类型
// IntFunction<R> int -> R
// LongFunction<R> long -> R
// DoubleFunction<R> double -> R
// IntToLongFunction int -> long
// IntToDoubleFunction int -> double
// LongToIntFunction long -> int
// LongToDoubleFunction long -> double
// DoubleIntFunction double -> int
// DoubleToLongFunction double -s long
//Supplier<T> : 参数无 返回T
//UnaryOperator : 参数T,R 返回T
//BiFunction<T,U,R> : 参数T,U 返回R
//BiConsumer<T,U> : 参数T,U 返回值void
}
}
消费型接口
@Test
public void test01(){
//Consumer
Consumer<Integer> consumer = (x) -> System.out.println("消费型接口" + x);
//test
consumer.accept(100);
}
提供型接口
@Test
public void test02(){
List<Integer> list = new ArrayList<>();
List<Integer> integers = Arrays.asList(1,2,3);
list.addAll(integers);
//Supplier<T>
Supplier<Integer> supplier = () -> (int)(Math.random() * 10);
list.add(supplier.get());
System.out.println(supplier);
for (Integer integer : list) {
System.out.println(integer);
}
}
函数型接口
@Test
public void test03(){
//Function<T, R>
String oldStr = "abc123456xyz";
Function<String, String> function = (s) -> s.substring(1, s.length()-1);
//test
System.out.println(function.apply(oldStr));
}
断言型接口
@Test
public void test04(){
//Predicate<T>
Integer age = 35;
Predicate<Integer> predicate = (i) -> i >= 35;
if (predicate.test(age)){
System.out.println("你该退休了");
} else {
System.out.println("我觉得还OK啦");
}
}
闭包问题
public class ClosureDemo {
public static void main(String[] args) {
int n = getNumber().get(); //get方法是Supplier接口
//闭包 提高变量的生命周期。getNumber方法结束时,变量应该销毁,但是输出了n。实现了Supplier方法,提高变量的生命周期
System.out.println(n);
}
private static Supplier<Integer> getNumber(){
int num = 100;
//闭包
return () -> {
return num;
};
}
}
public class ClosureDemo2 {
public static void main(String[] args) {
int a = 100; // 在编译时,会为int加上final, 从变量成为常量
Consumer<Integer> c = ele ->{
System.out.println(ele);
};
c.accept(a);
Consumer<Integer> c2 = ele ->{
System.out.println(a);
};
c2.accept(a);
//注意:在闭包中引用的一定是常量
// a++ 则报错
//Consumer<Integer> c2 = ele ->{
// System.out.println(a++);
//};
}
}
练习
package com.godfrey.lambda;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.Random;
import java.util.function.*;
import java.util.stream.Stream;
@SpringBootTest
class LambdaTest {
@Test
void functionInterfaceTest() {
//1.Supplier(提供型接口):没有输入,只有输出
Supplier<String> supplier = () -> "this is supplier demo for supplier";
System.out.println(supplier.get());
//2.Consumer(消费型接口):只有输入,没有输出
Consumer<String> consumer = i -> System.out.println("this is consumer demo for " + i);
consumer.accept("Consumer");
//3.Function(函数型接口):输入T,输出R
Function<Integer, Integer> function = i -> i * i;
System.out.println("Function demo: " + function.apply(9));
//4.Predicate(断言型接口):输入T,输出boolean
Predicate<Integer> predicate = (i) -> i == 2;
System.out.println(predicate.test(1));
//5.Function实现类,输入和输出类型一致
UnaryOperator<Integer> unaryOperator = i -> i * i;
System.out.println("UnaryOperator demo: " + unaryOperator.apply(8));
//6.输入T、U,输出R
BiFunction<Integer, Integer, String> biFunction = (i, j) -> i + "*" + j + "=" + i * j;
System.out.println(biFunction.apply(8, 9));
}
@Test
void streamTest() {
String[] arr = {"react", "", "spring", "bo_le", "webflux", "spring", "bo_le"};
//1.Arrays
Arrays.stream(arr).forEach(System.out::println);
//2.list
Arrays.asList(arr).stream().forEach(System.out::println);
//3.Stream.of
Stream.of(arr).forEach(System.out::println);
//4.迭代器 打印1-10元素
Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);
//5.generate 产生10个1-10随机数
Stream.generate(() -> new Random().nextInt(10)).limit(10).forEach(System.out::println);
}
@Test
void stream2Test() {
String[] arr = {"react", "", "spring", "bo_le", "webflux", "spring", "bo_le"};
//输出bole
Stream.of(arr).filter(i -> !i.isEmpty())
.distinct()
.sorted()
.limit(1)
.map(i -> i.replace("_", ""))
.flatMap(i -> Stream.of(i.split("")))
.forEach(i -> System.out.println(i));
}
}