Java基础-8新特性

Lambda 表达式

Lambda 表达式,也可称为闭包。Lambda 表达式是一个匿名函数,我们可以这样理解 Lambda 表达式:Lambda 是一段可以传递的代码(能够做到将代码像数据一样进行传递)。格式如下:

java 复制代码
(parameters) -> expression
或
(parameters) ->{ statements; }

实例

创建线程

java 复制代码
//不使用lambda
       new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },"thread").start();
//使用lambda
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
        }, "thread").start();

语法

Lambda 表达式在 Java 语言中引入了 "->" 操作符, "->" 操作符被称为 Lambda 表达式的操作符或者箭头操作符,它将 Lambda 表达式分为两部分:

  • 左侧部分指定了 Lambda 表达式需要的所有参

  • 右侧部分指定了 Lambda 体,即 Lambda 表达式要执行的功能

Lambda 表达式本质上是对接口的实现,Lambda 表达式的参数列表本质上对应着接口中方法的参数列表。

语法格式一

无参,无返回值,Lambda 体只有一条语句

Runnable runnable=()-> System.out.println(Thread.currentThread().getName());
new Thread(runnable).start();

语法格式二

需要参数,并且无返回值。Lambda 表达式的参数列表的数据类型可以省略不写,因为 JVM编译器能够通过上下文推断出数据类型,这就是"类型推断"

public class LambdaDemo {
    interface Operate {
        void method(int x, int y);
    }

    public static void main(String[] args) {
        //实现Operate接口
        Operate operate = (x, y) -> System.out.printf("%d\t%d", x, y);
        operate.method(100,200);
    }
}
/*
100    200
*/

语法格式三

只需要一个参数时,参数的小括号可以省略

public class LambdaDemo {
    interface Operate {
        void method(int x);
    }

    public static void main(String[] args) {
        Operate operate = x -> System.out.printf("%d", x);
        operate.method(100);
    }
}
/*
100
*/

语法格式四

需要参数,并且有返回值

public class LambdaDemo {
    interface Operate {
        int method(int x, int y);
    }

    public static void main(String[] args) {
        Operate operate = (x, y) -> {
            System.out.println(x + y);
            return x + y;
        };
        operate.method(100, 200);
    }
}
/*
300
*/

语法格式五

当 Lambda 体只有一条语句时,return 和大括号可以省

public class LambdaDemo {
    interface Operate {
        int method(int x, int y);
    }

    public static void main(String[] args) {
        Operate operate = (x, y) ->  x + y;
        System.out.println(operate.method(100, 200));
    }
}

函数式接口

Lambda 表达式需要函数式接口的支持,只包含一个抽象方法的接口,称为函数式接口。

  • 可以通过 Lambda 表达式来创建该接口的对象。

  • 可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

java提供了四大函数式接口:

Consumer 消费型接口

Consumer 接口是消费性接口,无返回值。

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Supplier 供给型接口

Supplier 接口是供给型接口,有返回值。

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

Function<T,R> 函数式接口

Function 接口是函数型接口,有返回值。

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Predicate 断言型接口

Predicate 接口是断言型接口,返回值类型为 boolean。

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

方法引用与构造器引用

方法引用

当要传递给 Lambda 体的操作,已经有实现的方法了,可以使用方法引用!方法引用就是操作符"::"将方法名和对象或类的名字分隔开来。使用方法如下:

  1. 类::静态方法

  2. 类::实例方法

     public static void main(String[] args) {
         List<Integer> list=new ArrayList<>();
         list.forEach(item->System.out.println(item));
         //等价
         list.forEach(System.out::println);
     }
    

构造器引用

格式如下所示: ClassName::new

与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法, 与构造器参数列表要与接口中抽象方法的参数列表一致!

    public static void main(String[] args) {
        Function<Integer, List<Integer>> function = ArrayList::new;
        List<Integer> list = function.apply(16);

        Supplier<List<Integer>> supplier = ArrayList::new;
        List<Integer> integers = supplier.get();
    }

数组引用

    public static void main(String[] args) {
        Function<Integer, Integer[]> function = Integer[]::new;
        //创建大小为16的数组
        Integer[] list = function.apply(16);
    }

Optional类

Optional 类是一个容器类,代表一个值存在或不存在,可以避免空指针异常。类常用方法:

  1. Optional.of(T t) : 创建一个 Optional 实例。
  2. Optional.empty() : 创建一个空的 Optional 实例。
  3. Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例。
  4. isPresent() : 判断是否包含值。
  5. orElse(T t) : 如果调用对象包含值,返回该值,否则返回 t。
  6. orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值。
  7. map(Function f): 如果有值对其处理,并返回处理后的 Optional,否则返回 Optional.emp ty()。
  8. flatMap(Function mapper):与 map 类似,要求返回值必须是 Optional。

Stream API

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执 行非常复杂的查找、过滤和映射数据等操作。Stream使用流程如下:

  1. 创建 Stream:一个数据源(如: 集合、数组), 获取一个流。
  2. 中间操作: 一个中间操作链,对数据源的数据进行处理。
  3. 终止操作(终端操作): 一个终止操作,执行中间操作链,并产生结果。

创建Stream

获取Stream

     public static void main(String[] args) {
		List<Integer> list=new ArrayList<>();
        //获取流
        list.stream();
        //获取平行流
        list.parallelStream();
     }

由数组创建

    public static void main(String[] args) {
        Stream<Integer> integerStream = Arrays.stream(new Integer[]{1, 2, -12, 0});
        IntStream intStream = Arrays.stream(new int[]{1, 2, 3, -1});
        LongStream longStream = Arrays.stream(new long[]{1L, 2L, 3L, -1L});
        DoubleStream doubleStream = Arrays.stream(new double[]{1.1, 2.1, 3.1, -1.1});
    }

由值创建

    public static void main(String[] args) {
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);
    }

由函数创建

由函数创建流可以创建无限流。

    public static void main(String[] args) {
        Stream<Integer> stream = Stream.iterate(0, integer -> integer + 1);
        //创建的是无限流  使用limit方法获取10个
        List<Integer> collect = stream.limit(10).collect(Collectors.toList());
        System.out.println(collect);

        Stream<ArrayList<Object>> generate = Stream.generate(ArrayList::new);
        List<ArrayList<Object>> collect1 = generate.limit(5).collect(Collectors.toList());
        System.out.println(collect1);
    }

中间操作

筛选与切片

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        //筛选被3整除的数
        List<Integer> collect = list.stream().filter(item -> Objects.equals(item % 3, 0)).collect(Collectors.toList());
        System.out.println(collect);
        //选取前5个
        List<Integer> collect1 = list.stream().limit(5).collect(Collectors.toList());
        System.out.println(collect1);
        //跳过前2个
        List<Integer> collect2 = list.stream().skip(2).collect(Collectors.toList());
        System.out.println(collect2);
        //去重
        List<Integer> collect3 = list.stream().distinct().collect(Collectors.toList());
        System.out.println(collect3);
    }

映射

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        List<String> collect = list.stream().map(String::valueOf).collect(Collectors.toList());
        System.out.println(collect);
    }

排序

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        List<Integer> collect = list.stream().sorted().collect(Collectors.toList());
        System.out.println(collect);
    }

终止操作

查找与匹配

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        System.out.println(list.stream().allMatch(item -> item > 5));
        System.out.println(list.stream().anyMatch(item -> item > 5));
        System.out.println(list.stream().noneMatch(item -> item > 5));
        Optional<Integer> any = list.stream().findAny();
        System.out.println(any.orElse(0));
        Optional<Integer> first = list.stream().findFirst();
        System.out.println(first.orElse(0));
    }

统计

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        System.out.println(list.stream().filter(Objects::isNull).count());
        Optional<Integer> max = list.stream().max(Integer::compareTo);
        System.out.println(max.orElse(0));
        Optional<Integer> min = list.stream().min(Integer::compareTo);
        System.out.println(min.orElse(0));
        list.stream().forEach(System.out::println);
    }

规约

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        System.out.println(list.stream().reduce(0, Integer::sum));
        Optional<Integer> reduce = list.stream().reduce(Integer::sum);
        System.out.println(reduce.orElse(0));
    }

收集

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(2, 4, 5, 6, 7, 3, 6);
        System.out.println(list.stream().filter(Objects::nonNull).collect(Collectors.toList()));
    }

接口的默认方法与静态方法

Java 8 中允许接口中包含具有具体实现的方法,该方法称为"默认方法",默认方法使用 default t关键字修饰。

  1. 选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称 和参数的默认方法会被忽略。
  2. 接口冲突。如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有 相同名称和参数列表的方法(不管方法是否是默认方法), 那么必须覆盖该方法来解 决冲突。

在 Java8 中,接口中允许添加静态方法,使用方式接口名.方法名。

相关推荐
白晨并不是很能熬夜4 分钟前
【JVM】字节码指令集
java·开发语言·汇编·jvm·数据结构·后端·javac
火烧屁屁啦10 分钟前
【JavaEE进阶】Spring AOP详解
java·spring·java-ee
卡布奇诺-海晨18 分钟前
JVM之Arthas的dashboard命令以及CPU飙高场景
java·spring boot
学c真好玩23 分钟前
Spring
java·后端·spring
沉默王二26 分钟前
更快更强!字节满血版DeepSeek在IDEA中真的爽!
java·前端·程序员
2301_8074492027 分钟前
字符串相乘——力扣
java·算法·leetcode
小五Z32 分钟前
RabbitMQ高级特性--消息确认机制
java·rabbitmq·intellij-idea
Kevinyu_43 分钟前
Maven
java·maven
nickxhuang1 小时前
【基础知识】回头看Maven基础
java·maven
日月星辰Ace1 小时前
jwk-set-uri
java·后端