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 Stream stream() : 返回一个顺序流
 default Stream parallelStream() : 返回一个并行流

方式二:通过数组
 static Stream stream(T[] array): 返回一个流

方式三:通过Stream 的of()
 public static Stream of(T... values) : 返回一个流

方式四:创建无限流
 迭代 public static Stream iterate(final T seed, final UnaryOperator f)
 生成 public static Stream 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对象
posted @   simp1e1  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示