Java新特性
一、Java新特性
-
Lambda表达式
-
函数式接口
-
方法引用
-
作用:在Java中主要用在Lambda表达式和方法引用(想使用Lambda表达式,接口必须为函数式接口)。
JDK8专门提供了@FunctionalInterface注解,用来进行编译检查。
已经使用过的函数式接口,比如Comparator等,多线程阶段学习的函数式接口有Runnable、Callable等。
注意:Comparable并没有被标记为函数式接口
内置的函数式接口
-
Consumer<T>:消费型接口(void accept(T t))。有参数,无返回值。
-
Supplier<T>:供给型接口(T get())。只有返回值,没有入参。
-
Function<T, R>:函数型接口(R apply(T t))。一个输入参数,一个输出参数,两种类型不可不同、可以一致。
-
Predicate<T>:断言型接口(boolean test(T t))。输入一个参数,输出一个boolean类型得返回值。
函数式接口 | 方法名 | 输入参数 | 输出参数 | 作用 |
---|---|---|---|---|
消费型接口Consumer | void accept(T t) | T | void | 对类型为T的对象进行操作 |
供给型接口Supplier | T get() | void | T | 返回类型为T的对象 |
函数型接口Function | R apply(T t) | T | R | 对类型为T的对象进行操作,返回类型为R的对象 |
断言型接口Predicate | boolean test(T t) | T | boolean | 对类型为T的对象进行操作,返回布尔类型结果 |
-
有返回值的Lambda表达式,如果方法体只有一条返回语句,可同时省略return和{}。
-
虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。
-
Lambda 规定接口中只能有一个需要被实现的抽象方法,不是规定接口中只能有一个方法,称为函数式接口。
->左面: 参数类型可以省略不写,自动类型推断。
如果只有一个参数,()可以省略不写。
->右侧: {}将方法体的具体内容包裹起来。
方法体中只有一条执行语句,{}可以省略不写。
public class TestMethodRef1 { public static void main(String[] args) { //使用匿名内部类实现 Consumer consumer = new Consumer<Integer>() { @Override public void accept(Integer i) { System.out.println(i); } }; consumer.accept(56); //使用lambda表达式实现 Consumer<Integer> consumer1 = (i)->System.out.println(i); consumer1.accept(56); //使用方法引用 Consumer<Integer> consumer2 = System.out::println; consumer2.accept(56); } }
-
对象引用::实例方法名
-
类名::静态方法名
-
类名::实例方法名
-
类名::new (也称为构造方法引用)
-
使用方法引用的要求:
1.方法体中只有一个调用方法的执行语句。
2.函数式接口中方法的参数 和 引用方法的参数个数、顺序必须相同
3.函数式接口中方法有返回值,引用的方法也必须有返回值
4.函数式接口中方法的参数类和引用方法的类型相同 或 为引用方法参数类型的子类。
5.函数式接口中方法的返回值和引用方法的返回值类型相同 或 为引用方法参数返回值类型的父类。
四、流式编程
1.介绍
它是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的聚合操作或者大批量数据操作。
Stream API借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。
同时,它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。
所以说,Java8中首次出现的 java.util.stream是一个函数式语言+多核时代综合影响的产物。
Stream有如下三个操作步骤:
① 创建Stream:从一个数据源,如集合、数组中获取流。
② 中间操作:一个操作的中间链,对数据源的数据进行操作。
③ 终止操作:一个终止操作,执行中间操作链,并产生结果。
当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终止操作。
终止操作将返回一个执行结果,这就是你想要的数据。
public class TestStream { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); Collections.addAll(list, 2,3,4,1,6,5); Stream<Integer> stream = list.stream();//获取stream流对象 stream.forEach(System.out::println); } }
3.中间操作和终止操作
public class TestStream2 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); Collections.addAll(list, 5, 4, 4, 3, 2, 1); /* 中间操作 */ Stream<Integer> stream = list.stream() .filter(t -> { //过滤, 获取符合条件元素 if (t > 1) { return true; } return false; }) .map(t -> t + 1) //将元素进行相关操作 .distinct() //去重 .sorted() //排序 .skip(1) //跳过1个 .limit(2); //返回2个 /* 终止操作 */ //将数据收集到Set集合中 //Set<Integer> set = stream.collect(Collectors.toSet()); //获取最大值 //Optional<Integer> max = stream.max(Integer::compareTo); //System.out.println(max.get()); //获取最小值 //Optional<Integer> min = stream.min(Integer::compareTo); //System.out.println(min.get()); //获取元素个数 //long count = stream.count(); //System.out.println(count); //变为数组 //Object[] objects = stream.toArray(); //获取第一个 //Optional<Integer> first = stream.findFirst(); //System.out.println(first.get()); //遍历获取每一个元素 stream.forEach(System.out::println); } }
4.创建Stream串行流
例:
使用ForkJoin和普通for实现1-1000000000000l求和效率对比。
public class SumTask extends RecursiveTask<Long> { private long start; private long end; private final int step = 2000000;//自定义步长 public SumTask(long start, long end) { this.start = start; this.end = end; } @Override //在这个方法中定义我们自己计算的规则 protected Long compute() { long sum = 0; //小于步长, 不再进行任务的拆分 if (end - start < step) { for (long i = start; i <= end; i++) { sum += i; } } else { long mid = (end + start) / 2; SumTask leftTask = new SumTask(start, mid); SumTask rightTask = new SumTask(mid + 1, end); //执行子任务 leftTask.fork(); rightTask.fork(); //子任务,执行完,得到执行结果 long leftSum = leftTask.join(); long rightSum = rightTask.join(); //System.out.println("join结果"+leftSum+"---"+rightSum); sum = leftSum + rightSum; } return sum; } public static void main(String[] args) throws ExecutionException, InterruptedException { long sum = 0; long l = System.currentTimeMillis(); for (long i = 1; i <= 100000000l; i++) { sum += i; } long l2 = System.currentTimeMillis(); System.out.println(sum); System.out.println("forx循环执行时间:" + (l2 - l)); //使用ForkJoin框架解决 //创建一个ForkJoin池 ForkJoinPool pool = new ForkJoinPool(); //定义一个任务 SumTask sumTask = new SumTask(1, 100000000l); long l3 = System.currentTimeMillis(); //将任务交给线程池 Future<Long> future = pool.submit(sumTask); long l4 = System.currentTimeMillis(); //得到结果并输出 Long result = future.get(); System.out.println(result); System.out.println("ForkJoin执行时间:" + (l4 - l3)); } }
4.2 获取并行流
public static void main(String[] args) throws ExecutionException, InterruptedException { List<Integer > list = new ArrayList<>(); Collections.addAll(list,34,56,89,65,87,80,87,95,100,34,45); //创建Stream方:并行流,底层采用ForkJoin框架,结果并不按照集合原有顺序输出 Stream stream2 = list.parallelStream();// stream2.forEach((x)->System.out.println(x+"---"+Thread.currentThread().getName())); }
5.Optional
5.1 介绍
Optional存在的意义就是简化 为了防止空指针异常的if-else 的代码
提供了全局value属性存储值
5.2 获取Optional对象
①
People people = null; Optional<People> optional = Optional.of(people); //java.lang.NullPointerException Optional<People> optional1 = Optional.ofNullable(people); //创建Optional对象
5.3 使用
5.3.1 参数为null
public class Demo { public static void main(String[] args) { //People people = null; 参数为null,两种方法都会执行 People people =new People();//参数不为null,只执行orElse() People t1 = Optional.ofNullable(people).orElse(getPeople("orElse")); People t2 = Optional.ofNullable(people).orElseGet(()->getPeople("orElseGet")); } public static People getPeople(String str){ System.out.println(str); return new People(); } }
5.3.2 获取Optional中存储的值
可以通过get()获取到全局value对应的值。
People people =new People();Optional<People> optional = Optional.ofNullable(people);People people = optional.get();
5.3.3 判断传递的参数是否为null
-
为null, 不会执行Consumer的实现。
-
People people =new People(); Optional.ofNullable(people).ifPresent(peo -> peo.setName("zs")); System.out.println(people.getName());
5.3.4 filter()过滤
Optional<People> people1 = Optional.ofNullable(people).filter(x -> { if (x.getA() > 60) { return true; } else { return false; } });
5.3.5 map()
People people = null; // People people =new People("zs", 10); Optional.ofNullable(people).map(u -> u.getAge()).ifPresent(t -> System.out.println(t)); //对象不为null, 打印结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix