14、Java8新特性
14、Java8新特性
速度更快
代码更少(增加了新的语法:Lambda 表达式)
强大的 Stream API
便于并行
最大化减少空指针异常:Optional
Nashorn引擎,允许在JVM上运行JS应用
Lambda表达式
- Lambda表达式的本质:作为 函数式接口的实例;(匿名函数)
- 函数式接口:只有一个抽象方法的接口;
外部类 --> 内部类 --> 匿名内部类 --> lambda表达式
语法:()->{};
形参列表 -> 方法体
Runnable r1 = new Runnable(){
public void run(){sout("匿名内部类实现接口");}
};
// 符合函数式接口, 使用lambda表示式实现 ----》
Runnable r2 = ()->sout("lambda表达式实现函数时接口");
表达式的简化:
多个参数类型,多条语句:
(int x,String y) -> { sout("都不能省略"); return ; } //1.参数类型唯一 :去形参类型 (x,y)->{} //类型推断 //2.参数只有一个 :去() x->{} //3.代码只有一句 :去{} (x,y)-> Integer.compare(x,y); //return也可以省略 //4.无参 ()-> {}
函数式接口:
在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口;
Java内置4大核心函数式接口:
消费型接口;Consumer<T> void accept(T t)
无返回值
供给型接口:Supplier<T> T get()
只出东西
函数型接口:Function<T> R apply(T t)
标准函数
断定型接口:Predicate<T> boolean test(T t)
判断真假其他接口:
BiFunction <T, U, R> R apply(T t, U u)
UnaryOperator <T> T apply(T t)
(Function 子接口)
BinaryOperator <T> T apply(T t1, T t2)
(BiFunction 子接口)
BiConsumer <T, U> void accept(T t, U u)
BiPredicate <T,U> boolean test(T t,U u)
int num = 1; //实例化接口调用 myMethod(1, new Predicate<Integer>() { public boolean test(Integer integer) { return integer%2==0; } }); //Lambda表达式调用 myMethod(1,(s)-> s%2==0 ); public void myMethod(int num,Predicate<Integer> p){ if (p.test(num)){ //p为函数式接口实例 System.out.println(num+ "为偶数"); }else { System.out.println(num+ "为奇数"); } }
方法引用与构造器引用
在Lambda表达式的基础上,进一步简化 --》
::
要求:实现接口的抽象方法 与 方法引用的方法 的 参数列表和返回值类型保持一致
构造器参数列表要与接口中抽象方法的参数列表一致!且方法的返回值即为构造器对应类的对象。 方法引用:
对象: :实例方法名
/ 类: :静态方法名 / 类: : 实例方法名
构造器引用:ClassName :: new
数组引用:type[] :: new
//1.方法引用 Comparator<Integer> com = (x,y)->Integer.compare(x,y); Comparator<Integer> com = Integer::compare; //2.构造器引用 Function<Integer,MyClass> fun = (n)->new MyClass(n); Function<Ingeger,MyClass> fun = MyClass::new; //3.数组引用 Function<Integer,Integer[]> fun = (n)->new Integer(n); Function<Integer,Integer[]> fun = Integer[]::new;
Stream API
Stream API 提供了一种高效且易于使用的处理数据的方式。 (数据库操作)
概述:
Stram关注的是对数据的运算 --CPU
集合关注的是对 数据的存储 -- 内存Stream 特点:
自己不会存储元素
不会改变源对象。而是返回一个持有结果的新Stream对象
操作时延迟执行的;等到需要结果的时候才执行;Stream执行流程:
1.Stream实例化
2.一系列的中间操作(过滤,映射。。)
3.终止操作 (一旦执行终止操作,就执行中间操作链,并产生结果)
Stram的实例化:
方式一:通过集合
default Streamstream() : 返回一个顺序流
default StreamparallelStream() : 返回一个并行流 方式二:通过数组
staticStream stream(T[] array): 返回一个流 方式三:通过Stream 的of()
public staticStream of(T... values) : 返回一个流 方式四:创建无限流
迭代 public staticStream iterate(final T seed, final UnaryOperator f)
生成 public staticStream generate(Supplier s)
//集合.stream() .parallelStream() Stream<Integer> stream1 = list.stream();//1.返回顺序流 Stream<Integer> stream2 = list.parallelStream(); //2.返回并行流 //Arrays.stream(arr) 数组创建 IntStream stream3 = Arrays.stream(arr); //Stream.of()创建 Stream<Object> stream4 = Stream.of(new Object[10]); //无限流 Stream.iterate .generate //迭代 --- 函数型接口 遍历前10个偶数 (从0开始,每次返回+2).限制10次.终止操作 Stream.iterate(0,x->x+2).limit(10).forEach(System.out::println); //生成 --- 供给型接口, 生成10个随机数 Stream.generate(Math::random).limit(10).forEach(System.out::println);
中间操作:
1-筛选与切片
//filter( 断定型接口 ) 过滤 stream.filter(x->x.getAge()>10).forEach(System.out::println); //distinct() 去重,(需要重写equals与hashCode) stream.distinct().forEach(x-> System.out.println(x)); //limit(long maxSize) 截取 stream.limit(5).forEach(x-> System.out.println(x)); //skip(long n) 跳过前n个(不足n个返回null) stream.skip(4).forEach(x-> System.out.println(x));
2-映射 .map
//map(函数型接口) 对某个属性(所有元素)进行映射(修改)操纵,并返回该属性 Stream<Integer> idStream = stream.map(x -> x.getId() + 100); //flatMap(Function f) -- 相对于: [1,2,3,[4,5] ] --》[1,2,3,4,5] //接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
3-排序 .sortred()
//1.自然排序 Stream<Integer> sorted = list1.stream().sorted(); //2.自定义排序 employees.stream().sorted((x1,x2)->{ return x1.getAge()-x2.getAge(); }); //返回新流 Stream<Employee> stream2
终止操作:
1- 匹配与查找
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意(随机一个)元素
//匹配 boolean b = stream.allMatch(x -> x.getAge() > 20); //返回首元素 Optional<Employee> first = employees.stream().findFirst();
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) (消费型接口) 内部迭代
//.count()元素总数 long count = employees.stream().count(); //.min() 流中的 首/尾 元素 (自然排序/自定义排序) employees.stream().max((x1, x2) -> x1.getAge()-x2.getAge());//Optional<Employee> employees.stream().min((x1, x2) -> Integer.compare(x1.getAge(),x2.getAge())); //forEach(消费型接口), 内部迭代 employees.stream().forEach(e-> System.out.println(e));
2-归约 .reduce(求和操作)
reduce(T iden, BinaryOperator b) 将流中元素反复结合起来,得到一个值。返回 T (iden是初始值)
reduce(BinaryOperator b) 将流中元素反复结合起来,得到一个值。返回 Optional
//.reduce(初始值,函数式接口) Integer reduce = list.stream().reduce(5, ((x1, x2) -> x1 + x2)); //求员工的 薪水总和 .map(映射薪水).reduce(元素总和) Optional<Double> reduce1 = employees.stream().map(x ->x.getSalary()).reduce((x1, x2) -> x1 + x2);
3-收集 .collect( ) 流转为集合
collect( Collectors.toSet() )
collect( Collectors.toList() )
collect( Collectors.toCollection() )Set<Employee> employeeSet = employees.stream().collect(Collectors.toSet()); List<Employee> employeeList = employees.stream().collect(Collectors.toList());
Optional类
Optional
类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。 创建Optional类对象:
Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
Optional.ofNullable(T t) :t可以为null获取Optional容器的对象:
T get(): 如果调用对象包含值,返回该值,否则抛异常,t必须非空;
T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。
Person p1 = new Person("张三", 10); Person p2 = null; Optional op = Optional.of(p2); //空指针异常 Optional op1 = Optional.ofNullable(p2); //T可以为 null Optional op2 = Optional.ofNullable(p1); Person pe1 = op1.orElse(new Person("空", 0)); //op1为null,返回 other对象 Perosn pe2 = op2.orElse(new Person("空", 0)); //op2不为null,返回op2对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)