java8特性

Lambda表达式

  1. lambda表达式:本质就是一个函数式接口的实例对象。
  2. 语法: lambda形参列表 箭头操作符 lambda体; lambda形参列表其实就是函数式接口中抽象方法的形参列表,lambda体就是重写函数式接口中抽象方法的方法体。
  3. 语法格式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");

// &#x5F53;lambda&#x5F62;&#x53C2;&#x5217;&#x8868;&#x7684;&#x5F62;&#x53C2;&#x503C;&#x6709;&#x4E00;&#x4E2A;&#x65F6;&#xFF0C;&#x5F62;&#x53C2;&#x5916;&#x9762;&#x7684;&#x5C0F;&#x62EC;&#x53F7;&#x53EF;&#x4EE5;&#x7701;&#x7565;
consumer = str -> {
    str = str.toUpperCase();
    System.out.println(str);
};
consumer.accept("helloworld");
</string>
  1. 语法格式3:lambda形参列表有一个以上的参数,有返回值
Comparator<string> comparator = (str1, str2) -> {
    return str1.compareTo(str2);
};
System.out.println(comparator.compare("Helm", "Hell"));
// lambda&#x4F53;&#x53EA;&#x6709;&#x4E00;&#x6761;return&#x8BED;&#x53E5;&#x65F6;&#x53EF;&#x4EE5;&#x7701;&#x7565;&#x5927;&#x62EC;&#x53F7;&#x548C;return&#x5173;&#x952E;&#x5B57;
comparator = (str1, str2) -> str1.compareTo(str2);
System.out.println(comparator.compare("Helm", "Hell"));
</string>
  1. 应用:
  2. 作为实参传递给方法形参为函数式接口的方法中
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表达式之前,是将匿名实现类对象赋值给接口定义的变量的。
// &#x533F;&#x540D;&#x5B9E;&#x73B0;&#x7C7B;
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&#x8868;&#x8FBE;&#x5F0F;
comparator = (o1, o2) -> Integer.compare(o1, o2);
System.out.println(comparator.compare(100, 200));
</integer></integer>

函数式接口

  1. 只包含一个抽象方法的接口叫做函数式接口。
  2. 在一个接口上面使用 @FunctionalInterface注解,可以检验该接口是否为函数式接口。
  3. Java中内置的函数式接口
  4. 消费性接口Consumer:对类型为T的对象应用操作,包含一个抽象方法accept。
  5. 供给型接口Supplier:返回类型为T的对象,包含一个抽象方法get。
  6. 函数型接口Function
  7. 断定型接口Predicate:检验类型为T的对象是否满足指定的条件,返回boolean类型的值。包含抽象方法test。
  8. 函数式接口BiFunction
  9. UnaryOperator:Function
  10. BinaryOperator:BiFunction
  11. BiConsumer
  12. BiPredicate
  13. ToIntFunction、ToLongFunction、ToDoubleFunction:对T类型的对象进行计算,分别返回int、long、double类型的返回值。
  14. IntFunction、LongFunction、DoubleFunction:分别对int、long、double类型的参数进行计算返回R类型的对象。
@Test
public void testFilter() {
    // &#x83B7;&#x53D6;&#x96C6;&#x5408;&#x4E2D;&#x5305;&#x542B;&#x5F20;&#x5B57;&#x7684;&#x5B57;&#x7B26;&#x4E32;
    List<string> list = new ArrayList<>();
    list.add("&#x5F20;&#x4E09;");
    list.add("&#x674E;&#x56DB;");
    list.add("&#x5F20;&#x838E;");
    list = filter(list, str -> str.contains("&#x5F20;"));
    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;
}
</string></string></string></string></string>

方法引用、构造器引用

1.方法引用
  1. 方法引用:使用lambda表达式时,对于lambda体中的操作,已经存在现成的方法可以使用,则可以直接使用。方法引用本质就是lambda表达式,它也可以作为一个函数式接口的实例对象。
  2. 方法引用的使用格式:类或者对象::方法名。具体分为三种情况:
  3. 对象::实例方法
Consumer<string> consumer = (str) -> System.out.println(str);
consumer.accept("helloworld");

// &#x65B9;&#x6CD5;&#x5F15;&#x7528;&#x7684;&#x60C5;&#x51B5;1&#x5B9E;&#x4F8B;
consumer = System.out::println;
consumer.accept("helloworld");
</string>
  1. 类::静态方法。对于情况1和情况2要求:函数式接口中抽象方法的形参列表和返回值类型与方法引用的方法相同。
Comparator<integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(comparator.compare(100, 200));
// &#x65B9;&#x6CD5;&#x5F15;&#x7528;&#x7684;&#x60C5;&#x51B5;2&#x793A;&#x4F8B;
comparator = Integer::compare;
System.out.println(comparator.compare(100, 200));
</integer>
  1. 类::实例方法,这种情况下,lambda形参列表中的第一个参数作为方法的目标。
BiPredicate<string, string> predicate = (str1, str2) -> str1.equals(str2);
System.out.println(predicate.test("Hello", "Hello"));
// &#x65B9;&#x6CD5;&#x5F15;&#x7528;&#x7684;&#x60C5;&#x51B5;3&#x793A;&#x4F8B;
predicate = String::equals;
System.out.println(predicate.test("Hello", "Hello"));
</string,>
2.构造器引用
  1. 构造器引用:和方法引用类似,函数式接口中抽象方法的形参列表和构造器的形参列表一样。抽象方法的返回值类型即为构造器所属的类的类型。
BiFunction<string, integer, student> function = (name, age) -> new Student(name, age);
Student student = function.apply("NrvCer", 23);
System.out.println(student);

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

// &#x6570;&#x7EC4;&#x5F15;&#x7528;
function = String[]::new;
strings = function.apply(10);
System.out.println(Arrays.toString(strings));
</integer,>

Stream API

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

1.Stream的创建
  1. 从数据源中获取Stream。创建Stream的方式有如下几种:
  2. 通过Collection接口的stream和parallelStream方法,前者返回顺序流、后者返回并行流
List<student> students = Student.getStudents();
// &#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x987A;&#x5E8F;&#x6D41;
Stream<student> stream = students.stream();
// &#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x5E76;&#x884C;&#x6D41;
Stream<student> parallelStream = students.parallelStream();

</student></student></student>
  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());
</list<student>
  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. 筛选:
  2. filter(Predicate p):接收lambda表达式,从流中排除符合条件的元素
  3. distinct():通过元素的hashCode和equals方法去除重复元素
List<student> students = Student.getStudents();
Stream<student> stream = students.stream();
// &#x67E5;&#x8BE2;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x5E74;&#x9F84;&#x5927;&#x4E8E;24&#x5C81;&#x7684;&#x5B66;&#x751F;&#x4FE1;&#x606F;
stream.filter(student -> student.getAge() > 24)
        .forEach(System.out::println);

// &#x53BB;&#x9664;&#x6D41;&#x4E2D;&#x7684;&#x91CD;&#x590D;&#x5143;&#x7D20;

// &#x4E00;&#x65E6;&#x4E00;&#x4E2A;&#x6D41;&#x6267;&#x884C;&#x4E86;&#x7EC8;&#x6B62;&#x64CD;&#x4F5C;&#xFF0C;&#x5176;&#x72B6;&#x6001;&#x4F1A;&#x6539;&#x53D8;
// stream has already been operated upon or closed
stream = students.stream();
stream.distinct().forEach(System.out::println);
</student></student>
  1. 切片:
  2. limit(long maxSize):截断流,使得其元素不超过给定的数量
  3. skip(long n):跳过元素,返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流。
  4. 映射:
  5. map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。类似的还有mapToDouble、mapToInt、mapToLong
// &#x83B7;&#x53D6;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x5B66;&#x751F;&#x5E74;&#x9F84;&#x5927;&#x4E8E;24&#x7684;&#x5B66;&#x751F;&#x5E74;&#x9F84;
List<student> students = Student.getStudents();
Stream<integer> ageStream = students.stream().map(Student::getAge);
// &#x5927;&#x4E8E;24&#x5C81;&#x7684;&#x5E74;&#x9F84;&#x96C6;&#x5408;
List<integer> result = new ArrayList<>();
ageStream.filter(age -> age > 24).forEach(age -> result.add(age));

</integer></integer></student>
  1. flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
  2. 排序
  3. sorted:产生一个新流,其中按照自然顺序排序
  4. sorted(Comparator comparator):产生一个新流,其中按照比较器顺序排序
List<integer> integers = Arrays.asList(23, 12, 34, 11, 56, 42);
// &#x81EA;&#x7136;&#x6392;&#x5E8F;
integers.stream().sorted().forEach(System.out::println);

// &#x5B9A;&#x5236;&#x6392;&#x5E8F;&#xFF1A;&#x5BF9;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x5148;&#x6309;&#x7167;&#x5E74;&#x9F84;&#x4ECE;&#x5C0F;&#x5230;&#x5927;&#x6392;&#x5E8F;&#xFF0C;
// &#x5E74;&#x9F84;&#x76F8;&#x540C;&#x518D;&#x6309;&#x7167;&#x59D3;&#x540D;&#x6392;&#x5E8F;
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);
</student></integer>
3.Stream的终止操作

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

  1. 匹配与查找
  2. allMatch(Predicate p):检查是否匹配所有元素
  3. anyMatch(Predicate p):检查是否至少匹配一个元素
  4. noneMatch(Predicate p):检查是否没有匹配的元素
  5. findFirst():返回流中第一个元素
  6. findAny():返回当前流中的任意元素
List<student> students = Student.getStudents();
// &#x68C0;&#x67E5;&#x662F;&#x5426;&#x6240;&#x6709;&#x5B66;&#x751F;&#x7684;&#x5E74;&#x9F84;&#x5927;&#x4E8E;20
boolean allMatch = students.stream().allMatch(student -> student.getAge() > 20);
System.out.println(allMatch);
// &#x68C0;&#x67E5;&#x662F;&#x5426;&#x5B58;&#x5728;&#x5B66;&#x751F;&#x7684;&#x59D3;&#x540D;&#x53EB;&#x505A;&#x5F20;&#x4E09;
boolean anyMatch = students.stream().anyMatch(student -> "&#x5F20;&#x4E09;".equals(student.getName()));
System.out.println(anyMatch);
// &#x68C0;&#x67E5;&#x662F;&#x5426;&#x5B58;&#x5728;&#x5B66;&#x751F;&#x7684;&#x59D3;&#x540D;&#x5305;&#x542B;&#x5218;
boolean noneMatch = students.stream().noneMatch(student -> student.getName().contains("&#x5218;"));
System.out.println(noneMatch);
// &#x83B7;&#x53D6;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x5B66;&#x751F;
Optional<student> student = students.stream().findFirst();
System.out.println(student.orElse(null));
// &#x83B7;&#x53D6;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x7684;&#x4EFB;&#x610F;&#x4E00;&#x4E2A;
Optional<student> any = students.stream().findAny();
System.out.println(any.orElse(null));
</student></student></student>
  1. 统计
  2. count():返回流中元素总数
  3. max(Comparator c):返回流中最大值
  4. min(Comparator c):返回流中最小值
  5. forEach(Consumer c):迭代
List<student> students = Student.getStudents();
// &#x83B7;&#x53D6;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x7684;&#x5B66;&#x751F;&#x4E2A;&#x6570;
System.out.println(students.stream().count());
// &#x83B7;&#x53D6;&#x5E74;&#x9F84;&#x6700;&#x9AD8;&#x7684;&#x5B66;&#x751F;
Student student = students.stream().max((v1, v2) -> Integer.compare(v1.getAge(), v2.getAge()))
        .orElse(null);
System.out.println(student);
// &#x83B7;&#x53D6;&#x957F;&#x5EA6;&#x6700;&#x77ED;&#x7684;&#x59D3;&#x540D;
Stream<string> nameStream = students.stream().map(Student::getName);
System.out.println(nameStream.min((s1, s2) -> s1.length() - s2.length()));

</string></student>
  1. 规约
  2. reduce(T identity, BinaryOperator b):可以将流中的元素反复结合起来,得到一个值,返回T
  3. reduce(BinaryOperator b):可以将流中的元素反复结合起来,得到一个值,返回Optional
// &#x8BA1;&#x7B97;&#x4E00;&#x4E2A;&#x6574;&#x5F62;&#x6570;&#x7EC4;&#x4E2D;&#x5143;&#x7D20;&#x7684;&#x548C;
List<integer> integers = Arrays.asList(0, 10, 20, 40, 60, 80, 100);
Integer result = integers.stream().reduce(0, Integer::sum);
System.out.println(result);
</integer>
  1. 收集
  2. collect(Collector c):将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
// &#x67E5;&#x627E;&#x5B66;&#x751F;&#x96C6;&#x5408;&#x4E2D;&#x5E74;&#x9F84;&#x5927;&#x4E8E;23&#x5C81;&#x7684;&#x5B66;&#x751F;&#xFF0C;&#x7ED3;&#x679C;&#x4FDD;&#x5B58;&#x5728;&#x53E6;&#x4E00;&#x4E2A;&#x96C6;&#x5408;&#x4E2D;
List<student> students = Student.getStudents();
List<student> ageList = students.stream().filter(student -> student.getAge() > 23)
        .collect(Collectors.toList());
ageList.forEach(System.out::println);
</student></student>

java8特性

java8特性

Optional类

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

1.Optional类常用的方法:
  1. 创建Optional类型的对象的方法:
  2. Optional.of(Tt):创建一个Optional实例,t必须非空;如果t为空,则抛出空指针异常
  3. Optional.ofNullable(T t):创建一个Optional实例,t可以为null
  4. Optional.empty() : 创建一个空的Optional实例
// &#x7A7A;&#x7684;Optional&#x5B9E;&#x4F8B;&#x5373;
private static final Optional<?> EMPTY = new Optional<>();
  1. 获取Optional容器包装的对象的方法
  2. T get():如果容器包装的value值不为空,则返回该值。否则抛出异常。
  3. T orElse(T other):
  4. orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.如果内部的t是空的,则返回orElse()方法中的参数t1
  5. orElseGet(Supplier other):如果Optional容器包装的对象不为空,则返回它。否则返回供给型接口提供的对象。
  6. orElseThrow(Supplier exceptionSupplier):如果Optional容器包装的对象不为空,则返回它。否则返回供给型接口提供的异常。
  7. 判断Optional容器是否包含对象
  8. boolean isPresent()
  9. void ifPresent(Consumer consumer):如果容器包装的value不为空,则执行消费性接口中的方法
Student student = null;
// ofNullable&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x63D0;&#x4F9B;&#x7A7A;&#x7684;&#x5B9E;&#x4F8B;&#x5BF9;&#x8C61;
Optional<student> optional = Optional.ofNullable(student);
// Optional&#x5185;&#x90E8;&#x5C01;&#x88C5;&#x7684;t&#x4E3A;&#x7A7A;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;orElse&#x7684;&#x5F62;&#x53C2;
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&#x5BF9;&#x8C61;&#x4E3A;&#x7A7A;&#xFF01;"));
// &#x7A7A;&#x6307;&#x9488;&#x5F02;&#x5E38;&#x5BF9;&#x8C61;
System.out.println(student);
</student></student>

Original: https://www.cnblogs.com/xiaocer/p/16720851.html
Author: 文件精度
Title: java8特性

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/615843/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Day6-笔记(数组、稀疏数组、冒泡排序、内存分析-堆-栈)

    数组的定义: 数据类型 [] 数组名 数组的四个基本特点: 1、长度确定,不可变,如果越界则报 ArrayIndexOuttoBoundsExpection 2、类型相同。数组是相…

    Java 2023年6月6日
    095
  • javax.xml.ws.Service 未定义未识别的错误

    可能缺失一个jar包. geronimo-jaxws_2.2_spec-1.1.jar.zip, 加入到编译指定的目录中。 http://www.java2s.com/Code/J…

    Java 2023年5月29日
    082
  • 接口回调与lambda表达式

    “接口回调”一词是借用了C语言中指针回调的术语,表示一个变量的地址在某一个时刻存放在一个指针变量中,那么指针变量就可以间接操作该变量中存放的数据。 和类一样…

    Java 2023年6月14日
    081
  • VS Code摸鱼神器,让你快速开发AI模型

    摘要:ModelArts VS Code插件一键接入云上开发环境介绍及操作指导 对于习惯于使用本地VS Code IDE的开发者,受限于本地资源,采用本地开发加云上调测的 远程开发…

    Java 2023年6月15日
    077
  • TCP 5连问,你能抗到第几轮?

    1,TCP3次握手具体过程 2,请聊聊SYN攻击 3,CLOSE-WAIT 和 TIME-WAIT的作用 4,TCP如何保证可靠性 5,TCP如何进行拥塞控制 答案解析 ​ TCP…

    Java 2023年6月15日
    079
  • java 8 新特性

    java8 是一个有里程碑的一个版本,提供了很多的新特性,但这些新特性是实打实有用的,而不是一些鸡肋 接口新特性 java8 之前,往接口里新加一个方法,那么所有的实现类都需要变动…

    Java 2023年6月8日
    073
  • SpringBoot 优雅配置跨域多种方式及Spring Security跨域访问配置的坑

    前言 最近在做项目的时候,基于前后端分离的权限管理系统,后台使用 Spring Security 作为权限控制管理, 然后在前端接口访问时候涉及到跨域,但我怎么配置跨域也没有生效,…

    Java 2023年6月13日
    0124
  • Java基础 awt Button 鼠标放在按钮上背景颜色改变,鼠标离开背景颜色恢复

    JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code packag…

    Java 2023年5月29日
    079
  • swing 监听器常用方法

    java Swing事件监听器 动作事件监听器ActionListener 添加/删除方法 addActionListener()、removeActionListener() 接…

    Java 2023年6月5日
    080
  • webupload项目中使用

    目前项目需要一个多图上传的功能,使用LayUI并也是可以实现多图上传的,但是没有图片删除功能,参考了一下网上多图上传的插件,选择了WebUpload进行功能开发。 然而不幸的是,官…

    Java 2023年6月9日
    077
  • 红黑树添加删除

    上一篇写了234树对比红黑树,和红黑树某些情况需要调整的原因,这篇就只写红黑树的添加和删除 红黑树 JAVA技术交流群:737698533 性质 每个节点要么红色要么黑色 根节点是…

    Java 2023年6月6日
    068
  • Java UUID的底层原理

    UUID的几个核心特定: 全局时空唯一性固定长度128比特,也就是16字节(1 byte = 8 bit)分配速率极高,单机每秒可以生成超过1000万个UUID(实际上更高) UU…

    Java 2023年5月29日
    069
  • List实体中不同字段值的转换

    //将sql查询出的List Original: https://www.cnblogs.com/gjths/p/14179140.htmlAuthor: ExpectoPatro…

    Java 2023年6月13日
    053
  • easyUI 自定义排序datagrid

    @author YHC 如果默认的排序行为不满足你的需求,你可以自定义datagrid排序行为. 最基础的用户可以定义一个排序函数,函数名是s orter 在列上,这个函数将接受两…

    Java 2023年5月29日
    056
  • C# 线程手册 第六章 线程调试与跟踪 跟踪开关

    当你的程序接近部署阶段时,你可能想从代码中去掉所有的跟踪和调试消息。然而,你不得不从代码中一条一条地寻找调试指令并将其去掉。对于这种情况你可以在程序编译期间使用编译标志处理。从Vi…

    Java 2023年5月29日
    077
  • RabbitMQ——Virtual Host

    Virtual Host 作用 Virtual Host 本质上是一个mini版的RabbitMQ服务器,拥有自己的队列、绑定、交换器和权限控制; Virtual Host 通过在…

    Java 2023年5月30日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球