首页 > 编程语言 >java8特性

java8特性

时间:2022-09-22 21:13:00浏览次数:63  
标签:stream System 特性 student println Optional java8 out

Lambda表达式

  1. lambda表达式:本质就是一个函数式接口的实例对象。
  2. 语法:lambda形参列表 箭头操作符 lambda体; lambda形参列表其实就是函数式接口中抽象方法的形参列表,lambda体就是重写函数式接口中抽象方法的方法体。
    1. 语法格式1:无参数,无返回值
    // lambda体中只有一条语句,可以省略大括号
    // Runnable runnable = () -> {System.out.println("HelloWorld");};
    Runnable runnable = () -> System.out.println("HelloWorld");
    runnable.run();
    
    1. 语法格式2:lambda形参列表有一个以上的参数,无返回值
    // 因为编译器存在类型推断,所以形参列表中的形参的数据类型可以省略
    Consumer<String> consumer = (str) -> {
        str = str.toUpperCase();
        System.out.println(str);
    };
    consumer.accept("helloworld");
    
    // 当lambda形参列表的形参值有一个时,形参外面的小括号可以省略
    consumer = str -> {
        str = str.toUpperCase();
        System.out.println(str);
    };
    consumer.accept("helloworld");
    
    1. 语法格式3:lambda形参列表有一个以上的参数,有返回值
    Comparator<String> comparator = (str1, str2) -> {
        return str1.compareTo(str2);
    };
    System.out.println(comparator.compare("Helm", "Hell"));
    // lambda体只有一条return语句时可以省略大括号和return关键字
    comparator = (str1, str2) -> str1.compareTo(str2);
    System.out.println(comparator.compare("Helm", "Hell"));
    
  3. 应用:
    1. 作为实参传递给方法形参为函数式接口的方法中
    String[] strs = new String[]{"Hi", "A", "Hello", "you"};
    Arrays.sort(strs, (str1, str2) -> str1.length() - str2.length());
    for (String str : strs) {
        System.out.println(str);
    }
    
    1. 赋值给接口定义的变量。在没有lambda表达式之前,是将匿名实现类对象赋值给接口定义的变量的。
    // 匿名实现类
    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return Integer.compare(o1, o2);
        }
    };
    System.out.println(comparator.compare(100, 200));
    // lambda表达式
    comparator = (o1, o2) -> Integer.compare(o1, o2);
    System.out.println(comparator.compare(100, 200));
    

函数式接口

  1. 只包含一个抽象方法的接口叫做函数式接口。
  2. 在一个接口上面使用@FunctionalInterface注解,可以检验该接口是否为函数式接口。
  3. Java中内置的函数式接口
    1. 消费性接口Consumer:对类型为T的对象应用操作,包含一个抽象方法accept。
    2. 供给型接口Supplier:返回类型为T的对象,包含一个抽象方法get。
    3. 函数型接口Function<T, R>:对类型为T的对象进行操作,返回类型为R的对象,包含抽象方法apply。
    4. 断定型接口Predicate:检验类型为T的对象是否满足指定的条件,返回boolean类型的值。包含抽象方法test。
    5. 函数式接口BiFunction<T, U, R>:对类型为T和U的两个对象进行操作,返回类型为R的对象,包含抽象方法apply。
    6. UnaryOperator:Function<T, T>的子接口,对类型为T的对象进行一元运算操作,返回类型为T的对象
    7. BinaryOperator:BiFunction<T,T,T>的子接口,对类型为T的两个对象进行操作,返回类型为T的对象
    8. BiConsumer<T, U>:对类型为T和U的两个对象应用操作
    9. BiPredicate<T, U>:检验类型为T和U的两个对象是否满足指定的条件,返回boolean类型的值
    10. ToIntFunction、ToLongFunction、ToDoubleFunction:对T类型的对象进行计算,分别返回int、long、double类型的返回值。
    11. IntFunction、LongFunction、DoubleFunction:分别对int、long、double类型的参数进行计算返回R类型的对象。
@Test
public void testFilter() {
    // 获取集合中包含张字的字符串
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    list.add("张莎");
    list = filter(list, str -> str.contains("张"));
    System.out.println(list);
}
public List<String> filter(List<String> list, Predicate<String> predicate) {
    ArrayList<String> resultList = new ArrayList<>();
    for (String str : list) {
        if (predicate.test(str)) {
            resultList.add(str);
        }
    }
    return resultList;
}

方法引用、构造器引用

1.方法引用
  1. 方法引用:使用lambda表达式时,对于lambda体中的操作,已经存在现成的方法可以使用,则可以直接使用。方法引用本质就是lambda表达式,它也可以作为一个函数式接口的实例对象。
  2. 方法引用的使用格式:类或者对象::方法名。具体分为三种情况:
    1. 对象::实例方法
    Consumer<String> consumer = (str) -> System.out.println(str);
    consumer.accept("helloworld");
    
    // 方法引用的情况1实例
    consumer = System.out::println;
    consumer.accept("helloworld");
    
    1. 类::静态方法。对于情况1和情况2要求:函数式接口中抽象方法的形参列表和返回值类型与方法引用的方法相同。
    Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
    System.out.println(comparator.compare(100, 200));
    // 方法引用的情况2示例
    comparator = Integer::compare;
    System.out.println(comparator.compare(100, 200));
    
    1. 类::实例方法,这种情况下,lambda形参列表中的第一个参数作为方法的目标。
    BiPredicate<String, String> predicate = (str1, str2) -> str1.equals(str2);
    System.out.println(predicate.test("Hello", "Hello"));
    // 方法引用的情况3示例
    predicate = String::equals;
    System.out.println(predicate.test("Hello", "Hello"));
    
2.构造器引用
  1. 构造器引用:和方法引用类似,函数式接口中抽象方法的形参列表和构造器的形参列表一样。抽象方法的返回值类型即为构造器所属的类的类型。
BiFunction<String, Integer, Student> function = (name, age) -> new Student(name, age);
Student student = function.apply("NrvCer", 23);
System.out.println(student);

// 构造器引用
function = Student::new;
student = function.apply("NrvCer", 24);
System.out.println(student);
  1. 数组引用:将数组作为一种类型,则写法和构造器引用一样
Function<Integer, String[]> function = length -> new String[length];
String[] strings = function.apply(4);
System.out.println(Arrays.toString(strings));

// 数组引用
function = String[]::new;
strings = function.apply(10);
System.out.println(Arrays.toString(strings));

Stream API

Stream:用于操作数据源所生成的元素序列,Java中的集合用于存储数据,而Stream一般用于计算。

1.Stream的创建
  1. 从数据源中获取Stream。创建Stream的方式有如下几种:
    1. 通过Collection接口的stream和parallelStream方法,前者返回顺序流、后者返回并行流
    List<Student> students = Student.getStudents();
    // 返回一个顺序流
    Stream<Student> stream = students.stream();
    // 返回一个并行流
    Stream<Student> parallelStream = students.parallelStream();
    
    
    1. 通过Arrays的静态方法stream获取数组流
    int[] arr = new int[]{1, 2, 3, 4, 5, 6};
    IntStream stream = Arrays.stream(arr);
    
    1. 通过Stream的of方法
    Stream<List<Student>> stream = Stream.of(Student.getStudents());
    
    1. 使用Stream的静态方法iterate和generate创建无限流
    Stream.iterate(100, value -> value + 100)
        .limit(10)
        .forEach(System.out::println);
    Stream.generate(Math::random)
        .limit(3)
        .forEach(System.out::println);
    
2.Stream的中间操作

一个中间操作链,对数据源的数据进行处理。只有触发了Stream的终止操作,中间操作才会执行。

  1. 筛选:
    1. filter(Predicate p):接收lambda表达式,从流中排除符合条件的元素
    2. distinct():通过元素的hashCode和equals方法去除重复元素
    List<Student> students = Student.getStudents();
    Stream<Student> stream = students.stream();
    // 查询学生集合中年龄大于24岁的学生信息
    stream.filter(student -> student.getAge() > 24)
            .forEach(System.out::println);
    
    // 去除流中的重复元素
    
    // 一旦一个流执行了终止操作,其状态会改变
    // stream has already been operated upon or closed
    stream = students.stream();
    stream.distinct().forEach(System.out::println);
    
  2. 切片:
    1. limit(long maxSize):截断流,使得其元素不超过给定的数量
    2. skip(long n):跳过元素,返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流。
  3. 映射:
    1. map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。类似的还有mapToDouble、mapToInt、mapToLong
    // 获取学生集合中学生年龄大于24的学生年龄
    List<Student> students = Student.getStudents();
    Stream<Integer> ageStream = students.stream().map(Student::getAge);
    // 大于24岁的年龄集合
    List<Integer> result = new ArrayList<>();
    ageStream.filter(age -> age > 24).forEach(age -> result.add(age));
    
    
    1. flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
  4. 排序
    1. sorted:产生一个新流,其中按照自然顺序排序
    2. sorted(Comparator comparator):产生一个新流,其中按照比较器顺序排序
    List<Integer> integers = Arrays.asList(23, 12, 34, 11, 56, 42);
    // 自然排序
    integers.stream().sorted().forEach(System.out::println);
    
    // 定制排序:对学生集合先按照年龄从小到大排序,
    // 年龄相同再按照姓名排序
    List<Student> students = Student.getStudents();
    students.stream()
            .sorted((v1, v2) -> {
        int ageResult = Integer.compare(v1.getAge(), v2.getAge());
        return ageResult == 0 ? v1.getName().compareTo(v2.getName()) : ageResult;
    }).forEach(System.out::println);
    
3.Stream的终止操作

一旦执行终止操作,就执行中间操作链,并产生结果。流进行了终止操作后,不能再次使用。

  1. 匹配与查找
    1. allMatch(Predicate p):检查是否匹配所有元素
    2. anyMatch(Predicate p):检查是否至少匹配一个元素
    3. noneMatch(Predicate p):检查是否没有匹配的元素
    4. findFirst():返回流中第一个元素
    5. findAny():返回当前流中的任意元素
List<Student> students = Student.getStudents();
// 检查是否所有学生的年龄大于20
boolean allMatch = students.stream().allMatch(student -> student.getAge() > 20);
System.out.println(allMatch);
// 检查是否存在学生的姓名叫做张三
boolean anyMatch = students.stream().anyMatch(student -> "张三".equals(student.getName()));
System.out.println(anyMatch);
// 检查是否存在学生的姓名包含刘
boolean noneMatch = students.stream().noneMatch(student -> student.getName().contains("刘"));
System.out.println(noneMatch);
// 获取学生集合中的第一个学生
Optional<Student> student = students.stream().findFirst();
System.out.println(student.orElse(null));
// 获取学生集合中的任意一个
Optional<Student> any = students.stream().findAny();
System.out.println(any.orElse(null));
  1. 统计
    1. count():返回流中元素总数
    2. max(Comparator c):返回流中最大值
    3. min(Comparator c):返回流中最小值
    4. forEach(Consumer c):迭代
List<Student> students = Student.getStudents();
// 获取学生集合中的学生个数
System.out.println(students.stream().count());
// 获取年龄最高的学生
Student student = students.stream().max((v1, v2) -> Integer.compare(v1.getAge(), v2.getAge()))
        .orElse(null);
System.out.println(student);
// 获取长度最短的姓名
Stream<String> nameStream = students.stream().map(Student::getName);
System.out.println(nameStream.min((s1, s2) -> s1.length() - s2.length()));

  1. 规约
    1. reduce(T identity, BinaryOperator b):可以将流中的元素反复结合起来,得到一个值,返回T
    2. reduce(BinaryOperator b):可以将流中的元素反复结合起来,得到一个值,返回Optional
// 计算一个整形数组中元素的和
List<Integer> integers = Arrays.asList(0, 10, 20, 40, 60, 80, 100);
Integer result = integers.stream().reduce(0, Integer::sum);
System.out.println(result);
  1. 收集
    1. collect(Collector c):将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
// 查找学生集合中年龄大于23岁的学生,结果保存在另一个集合中
List<Student> students = Student.getStudents();
List<Student> ageList = students.stream().filter(student -> student.getAge() > 23)
        .collect(Collectors.toList());
ageList.forEach(System.out::println);

Optional类

Optional类:为了避免程序中出现空指针异常

1.Optional类常用的方法:
  1. 创建Optional类型的对象的方法:
    1. Optional.of(Tt):创建一个Optional实例,t必须非空;如果t为空,则抛出空指针异常
    2. Optional.ofNullable(T t):创建一个Optional实例,t可以为null
    3. Optional.empty() : 创建一个空的Optional实例
    // 空的Optional实例即
    private static final Optional<?> EMPTY = new Optional<>();
    
  2. 获取Optional容器包装的对象的方法
    1. T get():如果容器包装的value值不为空,则返回该值。否则抛出异常。
    2. T orElse(T other):
    3. orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.如果内部的t是空的,则返回orElse()方法中的参数t1
    4. orElseGet(Supplier<? extends T> other):如果Optional容器包装的对象不为空,则返回它。否则返回供给型接口提供的对象。
    5. orElseThrow(Supplier<? extends X> exceptionSupplier):如果Optional容器包装的对象不为空,则返回它。否则返回供给型接口提供的异常。
  3. 判断Optional容器是否包含对象
    1. boolean isPresent()
    2. void ifPresent(Consumer<? super T> consumer):如果容器包装的value不为空,则执行消费性接口中的方法
Student student = null;
// ofNullable方法可以提供空的实例对象
Optional<Student> optional = Optional.ofNullable(student);
// Optional内部封装的t为空,则返回orElse的形参
Student stu = optional.orElse(new Student("default", -1));
System.out.println(stu);

student = null;
Optional<Student> optional = Optional.ofNullable(student);
student = optional.orElseGet(() -> new Student("nrvcer", 23));
System.out.println(student);

student = optional.orElseThrow(() -> new NullPointerException("student对象为空!"));
// 空指针异常对象
System.out.println(student);

标签:stream,System,特性,student,println,Optional,java8,out
From: https://www.cnblogs.com/xiaocer/p/16720851.html

相关文章

  • java8 list集合更具对象属性去重处理
    话不多说直接上代码 packagecom.leinuo.jvm.list;importjava.util.*;importjava.util.concurrent.ConcurrentHashMap;importjava.util.function.Function;imp......
  • Java SE 19 新增特性
    JavaSE19新增特性作者:Grey原文地址:博客园:JavaSE19新增特性CSDN:JavaSE19新增特性源码源仓库:Github:java_new_features镜像仓库:GitCode:java_new_features......
  • bash的基础特性(二)
    命令补全shell程序在接收到用户执行命令的请求,分析完成之后,最左侧的字符串会被当做命令;命令处理机制:查找内部命令;根据PATH环境变量中设定的目录,自左而右逐个搜索目录下......
  • Oracle的OMF 特性
    Oracle的OMF全称“Oraclemanagedfile”,关于这个概念的参考请自行查阅Oracle官方文档“UsingOracle-ManagedFiles”(http://download.oracle.com/docs/cd/B19306_01/serv......
  • BM50 两数之和(利用hashmap特性以提高效率实现目标)
    描述给出一个整型数组numbers和一个目标值target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。(注:返回的数组下标从1开始算起,保证target一定......
  • Java8之list.stream的常见使用
    List<Integer>list=newArrayList<Integer>();从小到大方法:Collections.sort(list);从大到小方法:Collections.sort(list,Collections.reverseOrder());stream获取l......
  • Java8 Stream使用汇总总结
    前言:近期在coding过程中经常使用到java8的Stream,故在此做个汇总总结,积累沉淀下常用方法,希望对读的人也有所帮助,下一篇总结下lambda。文章目录Java8Stream1Stream概......
  • C#特性 Attribute:AttributeUsage
     特性(Attribute):特性(Attribute)是用于在运行时传递程序中各种元素(比如程序集、类、构造函数、委托、枚举、事件、字段、接口、方法等)的行为信息的声明性标签。您......
  • 探索Java8:(五)Supplier和Consumer接口的使用
    Supplier是函数式编程的另一个接口,与Function、Predicate接口类似,区别在于Supplier不接收任何参数,只返回结果。Supplier的基本使用@FunctionalInterfacepublicinterfac......
  • Kubernetes(K8S)特性有哪些?
    Kubernetes简介Kubernetes是一个开源的,用于管理云平台中做个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单且高效,Kubernetes提供了应用部署,规划,更新......