什么是Lambda
- Lambda表达式也被称为箭头函数、匿名函数、闭包。
- Lambda表达式体现的是轻量级函数式编程思想。
- ‘->’ 符号式Lambda表达式核心操作符号,符号左侧是操作参数,符号右侧是操作表达式。
- JDK8 新特性。
我们来看一个Lambda的例子:
//1 匿名内部类
new Thread(new Runnable() {
public void run() {
System.out.println("threading....");
}
}).start();
//2 Lambda模式
new Thread(() -> {
System.out.println("Lambda threading....");
}).start();
Lambda表达式是对现有解决方案的语义化优化。需要根据实际需求考虑性能问题。
函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。@FunctionalInterface用来检测是否符合函数式接口。例如:
/**
* @program zookeeper
* @description: 用户身份认证标记接口
* @author: xyhua
* @create: 2019/11/26 22:31
*/
@FunctionalInterface
public interface IUserCredential {
/**
* 通过用户账号,验证用户身份信息的接口
* @param username
* @return
*/
String verifyUser(String username);
/**
* 默认方法 所有子类都可以调用
* @param username
* @return
*/
default String getCredential(String username) {
if("admin".equals(username)) {
return "admin " + "系统管理员";
} else if("manage".equals(username)) {
return "manage " + "用户管理员用户";
} else {
return "commons " + "普通会员用户";
}
}
/**
* 静态方法 可以通过类调用
* @param username
* @return
*/
static String validateUserName(String username) {
if(Objects.nonNull(username)) {
return username;
} else {
return "";
}
}
/**
* 从Object继承的方法 不会影响函数式接口
* @return
*/
String toString();
}
java中的Lambda表达式,核心就是一个函数式接口的实现。例如:
//1 匿名内部类
IUserCredential iu = new IUserCredential() {
@Override
public String verifyUser(String username) {
return "admin".equals(username)? "管理员":"会员";
}
};
//2 Lambda
IUserCredential iu1 = (String username) -> {
return "admin".equals(username)? "管理员":"会员";
};
java.util.function 函数式接口
-
java.util.function.Predicate
接收参数对象T,返回一个boolean类型结果。
Predicate<String> predicate = (String username) -> { return "admin".equals(username); }; System.out.println(predicate.test("admin")); System.out.println(predicate.test("manager"));
-
java.util.function.Consumer
接收参数对象T,不返回结果。
Consumer<String> consumer = (String message) -> { System.out.println("发送重要消息:" + message); System.out.println("发送消息结束"); }; consumer.accept("吃饭了");
-
java.util.function.Function<T,R>
接收参数对象T,返回结果对象R。
Function<String, Integer> function = (String gender) -> { return "male".equals(gender)?1:0; }; System.out.println(function.apply("male")); System.out.println(function.apply("female"));
-
java.util.function.Supplier
不接受参数,提供T对象对创建工厂。
Supplier<String> supplier = () -> { return UUID.randomUUID().toString(); }; System.out.println(supplier.get()); System.out.println(supplier.get());
-
java.util.function.UnaryOperator
接收参数对象T,返回结果对象T
UnaryOperator<String> unaryOperator = (String img) -> { img += "[100*200]"; return img; }; System.out.println(unaryOperator.apply("原图"));
-
java.util.function.Binaryoperator
接受两个T对象,返回一个T对象结果。
BinaryOperator<Integer> binaryOperator = (Integer i1, Integer i2) -> { return i1>i2?i1:i2; }; System.out.println(binaryOperator.apply(1,2));
Lambda表达式基本知识
Lambda表达式基本语法
- lambda表达式,必须和接口进行绑定。
- lambda表达式的参数,可以附带0个到1个参数,括号中的参数类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中的参数类型进行推导。
- lambda表达式的返回值,如果代码块只有一行,并且没有大括号,不用写return关键字,单行代码的执行结果会自动返回,如果添加了大括号,或者有多行代码,必须通过return关键字返回执行结果。
Lambda原理
- Lambda表达式在JVM底层解析成私有静态方法和匿名内部类型。
- 通过实现接口的匿名内部类型中接口方法调用静态实现方法,完成Lambda表达式的执行。
stream操作
批量数据 转化成 stream对象
//多个数据
Stream stream = Stream.of("admin", "tom", "damu");
//数组
String[] strArrays = new String[]{"xueqi", "lijie"};
Stream<String> stream1 = Arrays.stream(strArrays);
//列表
List<String> list = new ArrayList<>();
list.add("糖豆");
list.add("雪糕");
Stream<String> stream2 = list.stream();
//集合
Set<String> set = new HashSet<>();
set.add("糖豆");
set.add("雪糕");
Stream<String> stream3 = set.stream();
//Map
Map<String, Integer> map = new HashMap<>();
map.put("tom", 1000);
map.put("jerry", 2000);
Stream stream4 = map.entrySet().stream();
stream对象对于基本数据类型的功能封装
IntStream.of(new int[]{10, 20, 30}).forEach(System.out::println);
IntStream.range(11, 15).forEach(System.out::println);
IntStream.rangeClosed(1, 5).forEach(System.out::println);
stream对象 转化成 指定的数据类型
Stream stream = Stream.of("admin", "tom", "damu");
// 数组
Object[] objx = stream.toArray(String[]::new);
// 字符串
String str = stream.collect(Collectors.joining()).toString();
// 列表
List<String> collect = (List<String>) stream.collect(Collectors.toList());
// 集合
Set<Set> sets = (Set<Set>) stream.collect(Collectors.toSet());
// Map
Map<String, String> mapx = (Map<String, String>) stream.collect(Collectors.toMap(x ->x, y -> "value" + y));
stream集合操作
List<String> accountList = new ArrayList<>();
accountList.add("songjiang");
accountList.add("lujunyi");
accountList.add("wuyong");
accountList.add("linchong");
accountList.add("likui");
accountList.add("wusong");
// map() 中间操作,map()方法
accountList = accountList.stream().map(x -> "梁山好汉:" + x).collect(Collectors.toList());
accountList.forEach(System.out::println);
// filter() 添加过滤条件,过滤符合条件的用户
accountList = accountList.stream().filter(x -> x.length() > 5).collect(Collectors.toList());
accountList.forEach(System.out::println);
// peek() 中间操作,迭代数据完成数据的依次处理过程
accountList.stream()
.peek(x -> System.out.println("peek 1:" + x))
.peek(x -> System.out.println("peek 2:" + x))
.forEach(System.out::println);
// stream中对于数字运算的支持
List<Integer> intList = new ArrayList<>();
intList.add(20);
intList.add(19);
intList.add(7);
intList.add(87);
intList.add(2);
// skip() 中间操作,有状态,跳过部分数据
intList.stream().skip(3).forEach(System.out::println);
// limit() 中间操作,有状态,限制输出数据量
intList.stream().skip(3).limit(2).forEach(System.out::println);
// distinct() 中间操作,有状态,剔除重复的数据
intList.stream().distinct().forEach(System.out::println);
// sorted() 中间操作,有状态,排序
// max() 获取最大值
// min() 获取最小值
// reduce() 合并处理数据
Optional<Integer> reduce = intList.stream().reduce((sum, x) -> sum + x);
System.out.println(reduce.get());