目录
1 lambda表达式
- lambda本质上是一段匿名内部类
- 也可以是一段可传递的代码
- 完整的lambda由三部分组成:参数列表,箭头,声明语句
- 完整语法
(Type1 param1,Type2 param2,...,TypeN paramN) ->{
//执行语句块
}
- 大部分场景下,参数类型可以根据上下文环境推断出来,因此参数类型可以省略
(param1,param2,...,paramN) ->{
//执行语句块
}
- 当只有一个参数时小括号可以省略
param ->{
//执行语句块
}
- 当执行语句只有一行代码时,可以省略花括号,return和语句结尾的分号
param -> System.out.println("lambda")
1.1 类型推断
- 根据上下文信息推断出参数类型,而不需要显式声明
1.2 局部变量限制
- lambda表达式执行代码块中可以直接使用外部变量
- 被lambda表达式使用的外部变量必须显式声明为final,或者事实上是final
- 不建议在代码块中直接使用外部变量
2 函数式接口
- 只有一个抽象方法的接口
- lambda表达式就是用使用函数式接口来承接
- jdk中java.util.function包下定义了常用的函数式接口
- 注解@FunctionalInterface表名接口是函数式接口
2.1 Predicate 函数式接口
- 断言,用户判断是否符合条件
- 入参为泛型,返回值为true或者false
- 使用示例
public class App {
private void test(Predicate<String> predicate){
if (predicate.test("hello")){
System.out.println("is hello");
}else {
System.out.println("is not hello");
}
}
public static void main(String[] args) {
new App().test(s -> s.equals("hello"));
}
}
2.2 Supplier函数式接口
- 获取某种类型对象
- 无入参,返回泛型
- 使用示例
public class App {
private void test(Supplier<String> predicate){
System.out.println(predicate.get());
}
public static void main(String[] args) {
new App().test(() -> "hello");
new App().test(() -> {
return "123";});
}
}
2.3 Consumer函数式接口
- 消费者,消费某种类型对象
- 入参为泛型,无返回值
- 使用示例
public class App {
private void test(Consumer<String> predicate){
predicate.accept("123");
}
public static void main(String[] args) {
new App().test(str -> System.out.println("test==>"+str));
}
}
2.4 Function函数式接口
- 类型转换,将一种类型的对象转换为另外一种类型
- 入参为泛型,出参也为泛型
- 使用示例
public class App {
private void test(Function<String,Integer> function){
Integer apply = function.apply("123");
System.out.println("test==>"+apply);
}
public static void main(String[] args) {
new App().test(str -> Integer.valueOf(str)+1);
}
}
2.5 Runnable函数式接口
- 执行某段功能逻辑代码
- 无入参,无出参
- 使用示例
public class App {
private void test(Runnable runnable){
runnable.run();
}
public static void main(String[] args) {
new App().test(() -> System.out.println("run"));
}
}
3 方法引用和构造器引用
- lambda表达式的简写方式
- 语法格式
类名::方法名
对象::方法名
3.1 对象方法引用
- 入参为一个时
public class App {
public static void main(String[] args) {
Consumer<String> c1 = str -> System.out.println(str);
c1.accept("hello1");
Consumer<String> c2 = System.out::println;
c2.accept("hello2");
}
}
- lambda入参均作为执行方法入参
- 执行方法入参个数以及方法返回值需要和函数式接口(即lambda表达式)保持一致
- 入参为两个时
public class App {
public static void main(String[] args) {
BiFunction<String, String, Boolean> b1 = (a,b)->a.equals(b);
System.out.println(b1.apply("a","b"));
BiFunction<String, String, Boolean> b2 = String::equals;
System.out.println(b2.apply("a","b"));
}
}
- 第一个参数作为方法调用者
- 其余参数作为执行方法入参
- 执行方法入参个数+1=函数式接口(即lambda表达式)所需要参数
- 执行方法返回值需要和函数式接口(即lambda表达式)保持一致
3.2 静态方法引用
public class App {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> b1 = (a,b)->Integer.compare(a,b);
System.out.println(b1.apply(1,2));
BiFunction<Integer, Integer, Integer> b2 = Integer::compare;
System.out.println(b2.apply(1,2));
}
}
- 执行方法入参个数以及方法返回值需要和函数式接口(即lambda表达式)保持一致
- lambda入参均作为执行方法入参
3.3 构造方法引用
- 无参构造引用
public class App {
public static void main(String[] args) {
Supplier<String> s1 = () -> new String();
System.out.println(s1.get());
Supplier<String> s2 = String::new;
System.out.println(s2.get());
}
}
- 带参构造引用
public class App {
public static void main(String[] args) {
Function<String,Integer> s1 = (a) -> new Integer(a);
System.out.println(s1.apply("123"));
Function<String,Integer> s2 = Integer::new;
System.out.println(s2.apply("123"));
}
}
4 stream API
- 简化代码
- 支持并行流
- 流对象只能使用一次
4.1 获取流
- 集合获取流
- Map获取流
public class App {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.keySet().stream().forEach(System.out::println);
map.values().stream().forEach(System.out::println);
}
}
- 数组获取流
public class App {
public static void main(String[] args) {
String[] arr = new String[]{
"hello","world"};
Stream<String> stream = Stream.of(arr);
stream.forEach(System.out::println);
}
}
4.2 流的筛选
4.2.1 过滤
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.stream().filter(s -> !s.equals("2")).forEach(System.out::println);
}
}
4.2.2 去重
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
list.stream().distinct().forEach(System.out::println);
}
}
4.2.3 获取前几条
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.stream().limit(2).forEach(System.out::println);
}
}
4.2.4 跳过几条
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.stream().skip(1).forEach(System.out::println);
}
}
4.3 映射
4.3.1 map类型转换
- 类型T转换为类型R
- 一对一转换
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.stream().map(Integer::valueOf).forEach(System.out::println);
}
}
4.3.2 flatMap类型转换
- 类型T转换为类型R的流
- 一对多转换
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
list.stream().flatMap(s -> Stream.of(s.split(","))).forEach(System.out::println);
}
}
4.4 匹配
4.4.1 任意一条匹配为true
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
boolean b = list.stream().anyMatch(s -> s.contains("2"));
System.out.println(b);
}
}
4.4.2 全部匹配成功为true
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
boolean b = list.stream().allMatch(s -> s.contains("2"));
System.out.println(b);
}
}
4.4.3 都不匹配为true
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
boolean b = list.stream().noneMatch(s -> s.contains("6"));
System.out.println(b);
}
}
4.5 查找
4.5.1 查询任意元素
- 返回任意元素
- 在非并行流中,返回的总是第一个元素
- 在并行流中,返回的哪个元素不确定
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
Optional<String> any = list.stream().findAny();
System.out.println(any);
}
}
4.5.2 查询第一个元素
public class App {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("1,2,3");
list.add("2,3,4");
list.add("3,4,5");
Optional<String> any = list.stream().findFirst();
System.out.println(any);
}
}
4.6 归约
4.6.1 同一类型两个数据合并为一个数据
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Optional<Integer> any = list.stream().reduce(Integer::sum);
System.out.println(any);
}
}
4.6.2 求最大值
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Optional<Integer> any = list.stream().max(Integer::compare);
System.out.println(any);
}
}
4.6.3 求最小值
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Optional<Integer> any = list.stream().min(Integer::compare);
System.out.println(any);
}
}
4.7 汇总统计
4.7.1 汇总操作
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//汇总为set集合
Set<Integer> collect = list.stream().collect(Collectors.toSet());
System.out.println(collect);
//汇总为map集合,当存在重复key是会报错
Map<Integer, Integer> collect1 = list.stream().collect(Collectors.toMap(key -> key, value -> value));
System.out.println(collect1);
list.add(2);
//按照值分组
Map<Integer, List<Integer>> collect2 = list.stream().collect(Collectors.groupingBy(key -> key));
System.out.println(collect2);
}
}
4.7.2 求总数
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
long count = list.stream().count();
System.out.println(count);
}
}
4.8 遍历
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.stream().forEach(System.out::println);
}
}
5 并行流
- 在流对象的基础上调用parallel(),返回的是并行流对象
- 或者直接调用集合的parallelStream()方法
- 依赖ForkJoin并行框架
6 新日期API
- java.time包
6.1 LocalDate
6.2 LocalTime
7 接口的默认方法和静态方法
7.1 接口默认方法
- default修饰
- 子类可以不用实现
7.2 接口静态方法
8 方法参数反射
- 在class文件中·保存方法参数名
- 默认不保留参数名
- 编译时通过参数 -parameters指定保存方法参数名