首页 > 编程语言 >JAVA8新特性

JAVA8新特性

时间:2023-05-04 22:45:46浏览次数:44  
标签:Author age Authors 特性 add authors new JAVA8

JAVA8新特性

Lambda表达式

只有函数式接口才能使用Lambda表达式

​ Lambda表达式是JDK8中的一个语法糖,它可以对某些匿名内部类的写法进行简化,它是函数式编程思想的一个重要体现,让我们不用关注是什么对象,而是更关注我们对数据进行了什么操作。

核心原则

​ 可推导可省略

基本格式

(参数列表)-> {方法体(函数式接口方法的方法体)}

示例

1、

// 返回数组中能被2整除的数字 
printNum(x-> x % 2 == 0 );
 
 public static void printNum(IntPredicate predicate) {
    int[] arr = {1,2,3,4,5,6,7,8,9,10};
    for (int i : arr) {
        // predocate.test() 方法返回值为boolean类型
         if (predicate.test(i)) {
             System.out.println(i);
         }
    }
}

结果:

2
4
6
8
10

2、

    final Integer integer = typeConver(s -> {
        s += "78";
        return Integer.parseInt(s);
    });
    System.out.println(integer);
}

public static <R> R typeConver (Function <String, R > function){
    String str = "12345";
    R result = function.apply(str);
    return result;
}

结果:

1234578

Lambda核心是通过实现函数式接口的方法来完成相应业务

Lambda表达式的省略原则

没有参数,没有返回值的抽象方法

() -> {方法体语句}
如果方法体语句只有一句,此时可以省略大括号
() -> 方法体语句

有一个参数,没有返回值的抽象方法

(x)->{方法体语句}
如果只有一个参数,参数的小括号也可以省略不写
x -> {方法体语句}

有多个参数,没有返回值的抽象方法

(a,b)->{方法体语句}

有多个参数,有多条方法体语句,有返回值的抽象方法

(x,y)->{double pow = Math.pow(x,y);  return pow;};
如果语句只有一条,大括号可以省略,如果单语句是return语句,则return关键字也可以去掉,该格式会自动返回内容  写return关键字必须写大括号
(x,y)->Math.pow(x,y);

Stream流

​ JAVA8的Stream流使用的是函数式编程模式,如同他的而名字一样,它可以被用来对集合或者数据及逆行链状流式的操作。可以更方便的让我们对集合或者数组进行操作。

集合获取流对象的方式:

list、set:
	list/set.stream();
map:
	 hm.keyset().stream();
	 hm.values().stream();
	 hm.entryset().stream();
数组:
	Stream.of(arr);

中间操作

filter过滤操作

可以对流中的元素进行条件筛选,过滤条件为 true 的才会保存在流中

示例:

@Test
public void testStream() {
    List<Integer> list  = new ArrayList<>();
    for (int i = 1; i < 11; i++) {
        // 添加1-10
        list.add(i);
    }
    list.stream().filter(x -> x%2==0).forEach(System.out::println);
}

结果:

2
4
6
8
10

map

​ 可以对流中的元素进行计算或转换

  • 类型转换
// 定义一个 作者类
class Author {
    private String name;
    private Integer age;

    public Author() {
    }

    public Author(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

/*-------------------------------------------*/
List<Author> authors = new ArrayList<>();
authors.add(new Author("迪迦",10));
authors.add(new Author("戴拿",11));
authors.add(new Author("盖亚",12));
// 类型转换,匿名内部类方式实现
authors.stream()
    // 类型转换: 输入Author类型的参数,输出String类型的参数
    .map(new Function<Author, String>() {

    @Override
    public String apply(Author author) {
        return author.getName();
    }
}).forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        System.out.println(s);
    }
});
}
// 类型转换,Lambda表达式实现
authors.stream().map(author -> author.getName()).forEach(s -> System.out.println(s));

结果:

迪迦
戴拿
盖亚
  • 计算
List<Author> authors = new ArrayList<>();
authors.add(new Author("迪迦",10));
authors.add(new Author("戴拿",11));
authors.add(new Author("盖亚",12));
authors.stream().map(author -> author.getAge()).map(age -> age + 10).forEach(age -> System.out.println(age));

结果:

20
21
22

distinct 去重

​ 可以去除流中的重复元素。

distinct方法是以来Object的equals方法来判断是否是相同的对象,所以集合中的对象需要重写equals方法

​ 示例:

​ 打印所有作家的名字,并且要求其中不能有重复元素


class Author {
    private String name;
    private Integer age;
	// 使用distinct操作必须重写equals和hashcode方法
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Author author = (Author) o;
        return Objects.equals(name, author.name) && Objects.equals(age, author.age);
    }
	// 显示对象数据必须重写toString方法
    @Override
    public String toString() {
        return "Author{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public Author() {
    }

    public Author(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

List<Author> authors = new ArrayList<>();
authors.add(new Author("迪迦",10));
authors.add(new Author("戴拿",11));
authors.add(new Author("迪迦",10));
// 去重
authors.stream().distinct().forEach(author -> System.out.println(author.getName()));

结果:

迪迦
戴拿

sorted 排序

​ 可以都流当中的元素进行排序

示例:

​ 对流中的元素进行降序排序,并且要求不能有重复的元素

  1. 调用空参的 sorted 方法

注意: 调用空参的排序方法,对象要实现Comparable接口,并重写compareTo()方法自定义排序规则

// 实现Comparable接口
class Author implements Comparable<Author>{
    private String name;
    private Integer age;
	// 重写compareTo()方法自定义排序规则
    @Override
    public int compareTo(Author o) {
        return this.getAge() - o.getAge();
    }
}


List<Author> authors = new ArrayList<>();
authors.add(new Author("迪迦",12));
authors.add(new Author("戴拿",11));
authors.add(new Author("盖亚",10));
authors.add(new Author("阿古茹",19));
authors.add(new Author("迪迦",12));
authors.stream().distinct().sorted().forEach(author -> System.out.println(author));

结果:

Author{name='盖亚', age=10}
Author{name='戴拿', age=11}
Author{name='迪迦', age=12}
Author{name='阿古茹', age=19}

​ 2.调用有参的 sorted 方法

List<Author> authors = new ArrayList<>();
authors.add(new Author("迪迦",12));
authors.add(new Author("戴拿",11));
authors.add(new Author("盖亚",10));
authors.add(new Author("阿古茹",19));
authors.add(new Author("迪迦",12));
// 匿名内部类方式
authors.stream().distinct().sorted(new Comparator<Author>() {
    @Override
    public int compare(Author o1, Author o2) {
        return o1.getAge()- o2.getAge();
    }
}).forEach(author -> System.out.println(author));
// Lambda表达式方式
authors.stream().distinct()
    .sorted((o1, o2) -> o1.getAge()-o2.getAge())
    .forEach(author -> System.out.println(author));

结果:

Author{name='盖亚', age=10}
Author{name='戴拿', age=11}
Author{name='迪迦', age=12}
Author{name='阿古茹', age=19}

limit 截取

​ 可以设置流的最大长度,超出的部分将被抛弃

示例:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
l.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).limit(2).forEach(authors -> System.out.println(authors));

结果:

Authors{name='迪迦', age=10}
Authors{name='戴拿', age=11}

skip 截取

​ 跳过流中前size个元素,截取剩余元素

示例:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
l.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).skip(2).forEach(authors -> System.out.println(authors));

结果:

Authors{name='赛罗', age=13}
Authors{name='艾斯', age=16}

flatMap

​ 把一个对象转换成多个对象作为流中的元素

示例:

List<Book> l1 = new ArrayList<>();
l1.add(new Book("西游记","孙悟空三打白骨精"));
l1.add(new Book("红楼梦","黛玉葬花"));
List<Book> l2= new ArrayList<>();
l2.add(new Book("鲁滨逊漂流记","海上流浪汉"));
l2.add(new Book("红楼梦","黛玉葬花"));
List<Book> l3 = new ArrayList<>();
l3.add(new Book("三国演义","司马懿统一"));
l3.add(new Book("红楼梦","黛玉葬花"));
List<Book> l4= new ArrayList<>();
l4.add(new Book("西游记","孙悟空三打白骨精"));
l4.add(new Book("水浒传","鲁智深倒拔垂杨柳"));
List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10,l1));
l.add(new Authors("戴拿",11,l2));
l.add(new Authors("赛罗",13,l3));
l.add(new Authors("艾斯",16,l4));
l.stream()
        .flatMap(authors -> authors.getBooks().stream())//从作家对象中中获取书的流对象
    .distinct() // 对书对象去重
  .forEach(books -> System.out.println(books.getName())); // 打印书的名字

// 作家信息
class Authors {
    private String name;
    private Integer age;
    private List<Book> books;

    public Authors() {
    }

    @Override
    public String toString() {
        return "Authors{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", books=" + books +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Authors(String name, Integer age, List<Book> books) {
        this.name = name;
        this.age = age;
        this.books = books;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Authors authors = (Authors) o;
        return Objects.equals(name, authors.name) && Objects.equals(age, authors.age) && Objects.equals(books, authors.books);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, books);
    }
}
// 进行去重操作必须重写hashcode方法和equals方法
class Book {
    private String name;
    private String content;

    @Override
    public String toString() {
        return "Books{" +
                "name='" + name + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Book() {
    }

    public Book(String name, String content) {
        this.name = name;
        this.content = content;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Book book = (Book) o;
        return Objects.equals(name, book.name) && Objects.equals(content, book.content);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, content);
    }
}

结果:

西游记
红楼梦
鲁滨逊漂流记
三国演义
水浒传

终结操作

​ 以当前方法作为流操作的终结方法,之后不能再进行流操作。

​ 流操作时必须要有一个终结操作,这样中间操作才会生效。

forEach 遍历

​ 对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么操作

示例:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
l.stream().forEach(authors -> System.out.println(authors.getName()));

结果:

迪迦
戴拿
赛罗
艾斯

count 数量

​ 获取当前流中元素的个数

count()方法不需要参数但是有一个返回值,需要被接收

示例:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final long count = l.stream().filter(authors -> authors.getAge() > 10).count();
System.out.println(count);

结果:

3

max 最大值

​ 获取流中的最大值

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final Optional<Authors> max = l.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(max.get());

结果:

Authors{name='艾斯', age=16, books=null}

min 最小值

​ 获取流中的最小值

示例:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final Optional<Authors> min = l.stream().min((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(min.get());

结果:

Authors{name='艾斯', age=16, books=null}

collect

​ 把当前流转换成一个集合

示例: toList\toSet

​ 获取一个存放所有作者名字的集合

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

final List<String> collect = l.stream().map(authors -> authors.getName()).collect(Collectors.toList());
System.out.println(collect);

结果:

[迪迦, 戴拿, 赛罗, 艾斯]

示例2: toMap

​ 获取一个Map集合,map的Key为姓名,value为年龄

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
// 匿名内部类方式实现
final Map<String, Integer> collect = l.stream().distinct().collect(Collectors.toMap(new Function<Authors, String>() {
    @Override
    public String apply(Authors authors) {
        return authors.getName();
    }
}, new Function<Authors, Integer>() {
    @Override
    public Integer apply(Authors authors) {
        return authors.getAge();
    }
}));
// Lambda表达式方式实现
final Map<String, Integer> collect = l.stream().distinct().collect(Collectors.toMap(authors -> authors.getName(), authors -> authors.getAge()));

System.out.println(collect);

结果:

{艾斯=16, 戴拿=11, 迪迦=10, 赛罗=13}

anyMatch

​ 判断是否有任意符合条件的元素,结果为boolean类型

示例:

​ 判断是否有年龄11岁以上的作家

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final boolean b = l.stream().anyMatch(authors -> authors.getAge() > 11);
System.out.println(b);

结果:

true

allMatch

​ 判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。

示例:

​ 是否年龄都为11岁以上的作家

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final boolean b = l.stream().allMatch(authors -> authors.getAge() > 11);
System.out.println(b);

结果:

false

noneMatch

​ 判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false。

示例:

​ 是否作家年龄都不大于30岁

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));
final boolean b = l.stream().noneMatch(authors -> authors.getAge() > 30);
System.out.println(b);

结果:

true

findAny

​ 获取流中的任意一个元素。该方法没有办法保证获取的一定是流中的第一个元素。

示例:

​ 获取任意一个年龄大于10的作家,如果存在就输出他的名字

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

final Optional<Authors> any = l.stream().filter(authors -> authors.getAge() > 10).findAny();
any.ifPresent(authors -> System.out.println(authors.getName()));

结果:

戴拿、赛罗、艾斯中的任意一个

findFirst

​ 获取流中的第一个元素

示例:

​ 获取一个年龄最小的作家的名字

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

final Optional<Authors> first = l.stream().sorted((o1, o2) -> {
    return o1.getAge()-o2.getAge();
}).findFirst();
first.ifPresent(authors -> System.out.println(authors.getName()));

结果:

迪迦

reduce 归并

​ 对流中的数据按照你制定的计算方式计算出一个结果

reduce内部的计算方式如下:

T result = identity; // 初始值
for (T element : this stream) // 遍历stream获取每个元素
	result = accumulator.apply(result,element);//计算方法
return result;

reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,他会按照我们的计算方式依次拿流中的元素和初始化值进行计算,计算结果再和后面的元素计算。

示例1:

T reduce(T identity, BinaryOperator<T> accumulator);

​ 求出所有作者的年龄的和

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

// 匿名内部类形式
final Integer reduce = l.stream().map(authors -> authors.getAge()).reduce(0, new BinaryOperator<Integer>() {
    @Override
    public Integer apply(Integer result, Integer element) {

        return result + element;
    }
});
// Lambda表达式
final Integer reduce = l.stream().map(authors -> authors.getAge()).reduce(0, (result, element) -> result + element);

System.out.println(reduce);

结果:

50

示例2:

​ 求所有作家中年龄的最大值

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

final Integer reduce = l.stream().map(authors -> authors.getAge()).reduce(Integer.MIN_VALUE, (result, element) -> result>element? result : element);
System.out.println(reduce);

结果:

16

示例3:

List<Authors> l = new ArrayList<>();
l.add(new Authors("迪迦",10));
l.add(new Authors("戴拿",11));
l.add(new Authors("赛罗",13));
l.add(new Authors("艾斯",16));

final Integer reduce = l.stream().map(author -> author.getAge()).reduce(Integer.MAX_VALUE, (result, element) -> result < element ? result : element);
System.out.println(reduce);

结果:

10

基本数据类型优化

​ 我们之前用到的很多Stream的方法都是由于使用了泛型。所以涉及到的参数和返回值都是引用数据类型。

​ 即使我们操作的是整数小数,但是实际用的都是他们的包装类。JDK5中引入的自动装箱和自动拆箱让我们在使用对应的包装类时就好像使用基本数据类型一样方便,但是我们应该清楚装箱和拆箱是要消耗时间的,虽然这个时间消耗很小,但是在大量的数据不断的重复装箱拆箱时,你就不能无视这个时间损耗了。

​ 所以为了让我们能够对这部分时间消耗进行优化,Stream还提供了很多专门针对基本数据类型的方法。

​ 例如: mapToInt、mapToLong、mapToDouble、flatMapToInt、flatMapToDouble等。

示例:

private static void test() {
	List<Author> author = getAuthors();
	authors.stream()
	.map(author -> author.getAge())  // Integer
	.map(age -> age + 10) // Integer -> int ->Integer
    .filter(age -> age>18)// Integer -> int ->Integer
    .map(age->age+2) // Integer -> int ->Integer
    .forEach(System.out::println);    
}

优化:

private static void test() {
	List<Author> author = getAuthors();
	authors.stream()
	.mapToInt(author -> author.getAge())  // int
	.map(age -> age + 10) // int
    .filter(age -> age>18)// int
    .map(age->age+2) // int
    .forEach(System.out::println);    
}

并行流

​ 当流中有大量元素时,我们可以使用并行流去提高操作效率。其实并行流就是把任务分配给多个线程去完成。如果我们自己去用代码实现的话会非常复杂,并且要求你对并发编程有足够的理解和认识。而如果我们使用Stream的话,我们只需要修改一个方法的调用就可以使用并行流来帮我们实现,从而提高效率。

parallel方法课可以把串行流转换成并行流

也可以通过parallelStream直接获取并行流对象

private static void test() {
    Stream<Integer> Stream = Stream.of(1,2,3,4,5,6,7,8,9,10);
    Integer sum  = stream.parallel()
        .peek(new Consumer<Integer>() {
            @Override
            public void acept(Integer num) {
                System.out.println(num + Thread.currentThread().getName());
            }
        })
        .filter(num -> num>5)
        .reduce((result,ele) -> result + ele)
        .get();
    
}
List<Author> author = getAuthors();
author.parallelStream()
    .map(author->author.getAge())
    .map(age->age+10)
    .filter(age->age>18)
    .map(age->age+2)
    .forEach(System.out::println)

Optional

​ 本质上Optional是一个包装类,可以把我们具体数据封装到Optional对象内部。然后我们去使用Optional中封装好的方法操作封装进去的数据就可以避免空指针异常。

Optional静态方法

Optional.ofNullable

​ 使用ofNullable来把数据封装成一个Optional对象。无论传入的参数是否为null都不会报异常。

Author author = new Author("迪迦",12);
author = null;
// 如果optional对象存在则进行消费
final Optional<Author> author1 = Optional.ofNullable(author);
author1.ifPresent(author2 -> System.out.println(author2.getAge()));

结果:

当author不为null时,  结果为12
当author为null时, 结果没有结果但是也不报错    

Optional.of

​ 如果你确定一个对象不为空,则可以使用Optional.of方法把数据封装成Optional对象。

如果对象为null,则会报出空指针异常

Author author = new Author("迪迦",12);
final Optional<Author> author2 = Optional.of(author);
author2.ifPresent(author3 -> System.out.println(author3.getAge()));

author = null;
final Optional<Author> author1 = Optional.of(author);
System.out.println(author1);
author = 

​ 结果:

12
npe 

Optional.empty

​ 将null封装成Optional对象。

Author author = new Author("迪迦",12);
author = null;
final Optional<Object> empty = Optional.empty();
// 判断值是否为null
System.out.println(empty.isEmpty());

​ 结果:

true

安全消费值

​ 如果一个对象是Optional对象,则可以调用消费接口进行消费,这个方法会判断Optional中封装的数据是否为空,不为空才会执行具体的消费代码。

这种写法可以避免空指针异常

Author author = new Author("迪迦",12);
author = null;
// 如果optional对象存在则进行消费
final Optional<Author> author1 = Optional.ofNullable(author);
author1.ifPresent(author2 -> System.out.println(author2.getAge()));

结果:

12

获取值

如果我们想获取值可以使用get方法获取,但是不推荐,因为当Optional内部的数据为空的时候会出现异常。

NoSucElement异常

Author author = new Author("迪迦",12);
final Optional<Author> author1 = Optional.ofNullable(author);
final Author author2 =
        author1.get();
System.out.println(author2);

author = null;
final Optional<Author> author3 = Optional.ofNullable(author);
final Author author4 = author3.get();
System.out.println(author4);

结果:

Author{name='迪迦', age=12}

Exception in thread "main" java.util.NoSuchElementException

安全获取值

orElseGet

​ 获取数据并且设置数据为空时的默认值。如果数据不为空就能获取到该数据,如果为空则根据你传入的参数来创建对象作为默认值进行返回。

示例:

Author author = new Author("迪迦",12);
// author = null;
Optional<Author> author1 = Optional.ofNullable(author);
Author author2 = author1.orElseGet(() -> new Author("戴拿",14));
System.out.println(author2);

结果:

// 当author不为空时,显示结果
Author{name='迪迦', age=12}
// 当author为null时,显示结果
Author{name='戴拿', age=14}

orElseThrow

​ 获取数据,如果数据不为空就能获取到该数据,如果为空则根据你传入的参数来创建异常抛出。

示例:

Author author = new Author("迪迦",12);
final Optional<Author> author1 = Optional.ofNullable(null);
final Author author2 = author1.orElseThrow(() -> new RuntimeException("测试异常"));
System.out.println(author2);

结果:

Exception in thread "main" java.lang.RuntimeException: 测试异常
	at com.Day23.newCharacter.Optional类.lambda$main$0(Optional类.java:16)
	at java.base/java.util.Optional.orElseThrow(Optional.java:408)
	at com.Day23.newCharacter.Optional类.main(Optional类.java:16)

过滤

​ 使用filter方法过滤出符合条件的Optional对象

示例:

Author author = new Author("迪迦",12);
final Optional<Author> author1 = Optional.ofNullable(author);
final Optional<Author> author3 = author1.filter(author2 -> author2.getAge() > 10);
System.out.println(author3);

结果:

// 当满足条件age为12时
Optional[Author{name='迪迦', age=12}]
// 当不满足条件age为10时,返回一个value为null的新的Optional对象
Optional.empty

判断

​ 可以使用isPresent/ifPresent方法判断是否存在数据。如果为空,返回值为false;如果不为空,返回值为true

推荐使用ifPresent,因为ifPresent更能体现Optional的优势

示例:

Author author = new Author("迪迦",12);
author = null;
// 如果optional对象存在则打印年龄
final Optional<Author> author1 = Optional.ofNullable(author);
author1.ifPresent(author2 -> System.out.println(author2.getAge()));

结果:

// 当Optional对象存在时
12
// 当Optional对象不存在时
什么也不显示

数据转换

​ Optional提供了map方法对数据进行转换,并且转换得到的数据也还是被Optional包装好的,保证了我们的使用安全。

示例:

// 将author转换为List<Book>
List<Book> l1 = new ArrayList<>();
l1.add(new Book("西游记","孙悟空三打白骨精"));
l1.add(new Book("红楼梦","黛玉葬花"));
final Optional<Authors> author = Optional.ofNullable(new Authors("迪迦", 12, l1));
Optional<List<Book>> books = author.map(authors -> authors.getBooks());
if (books.isPresent()) {
    System.out.println(books);
}

结果:

Optional[[Books{name='西游记', content='孙悟空三打白骨精'}, Books{name='红楼梦', content='黛玉葬花'}]]

方法引用

​ 简化Lambda表达式的语法糖

基本格式

​ 类名或者对象名::方法名

语法详解

引用类的静态方法

使用前提:

​ 如果我们在重写方法的时候,方法体中只有一行代码并且这行代码是调用了某个类的静态方法,并且我们要把重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法

格式
类名::方法名

引用对象的实例方法

格式
对象名::方法名

使用前提:

​ 如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个对象的抽象方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用对象的实例方法

引用类的实例方法

格式:
类名::方法名

使用前提:

​ 如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了第一个参数的抽象方法,并且我们把要重写的抽象方法中剩余的所有参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用类的实例方法

构造器引用

使用前提:

​ 如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的构造方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个构造方法中,这个时候我们就可以引用构造器

​ 如果方法体中的一行代码是构造器的话就可以使哟iing构造器引用

格式
类名::new

标签:Author,age,Authors,特性,add,authors,new,JAVA8
From: https://www.cnblogs.com/zzprogram/p/17372763.html

相关文章

  • java8新特性理解
    一些关于java8新特性理解引例在java中,考虑实现按学号顺序对学生List进行排序的功能。一.java8以前的实现方式:匿名内部类如果不使用java8的新特性,我们实现该功能通常会使用匿名内部类的方法。importjava.util.*;;classStudent{privateintid;privateStringn......
  • 22 对话陈华良(下)|成长快的那些人,都有什么特性?
    你好,我是辰洋,《郭东白的架构课》的项目负责人。上节课东白老师与华良老师就职业规划、职业选择模型等问题,互相交流了看法与意见。那么我们这节课继续,看他们还聊了些什么。主持人:郭东白瓜子二手车集团CTO嘉宾:陈华良每日优鲜技术VP,前美团算法委员会主席完整的对话视频如下:......
  • TPT19新特性之形式化需求:自动生成测试用例
     在测试形式化需求的主题上,我们又向前迈进了一步。 如今,已经可以使用TPT自动评估形式化需求。在TPT19中,相应的测试数据现在可以一键生成。 这还在测试中吗?是的,但是完全自动并且不需要创建复杂的测试用例。 这适用于哪种测试对象呢? 适用于可以使用TPT测试的所......
  • matlab编写,计及碳捕集电厂低碳特性的含风电电力系统源-荷多时间尺度调度方法
    matlab编写,计及碳捕集电厂低碳特性的含风电电力系统源-荷多时间尺度调度方法关键词:碳捕集电厂,风电,电力系统,碳交易机制,需求响应,多时间尺度。ID:4695671994531492......
  • JDK1.8新特性(七):默认方法,真香,开动!接口?我要升级!!
    前期回顾:JDK1.8新特性(一):JDK1.8究竟有哪些新特性呢JDK1.8新特性(二):为什么要关注JDK1.8JDK1.8新特性(三):Lambda表达式,让你爱不释手JDK1.8新特性(四):函数式接口JDK1.8新特性(五):Stream,集合操作利器,让你好用到飞起来JDK1.8新特性(六):Stream的终极操作,轻松解决集合分组、汇总等复杂......
  • vue学习 第十一天 CSS3新特性 ---- 新增选择器(1、属性选择器 2、结构伪类选择
    CSS3新特性1、CSS3现状1)新增的CSS3特性有兼容性问题,ie9+才支持2)移动端支持优于PC端3.)不断改进中,应用相对广泛 2、CSS3新增选择器CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素。1)属性选......
  • vue学习 第十天(2) HTML5的新特性 ----- 语义化标签(布局标签)/ 多媒体标签(video、
    目标:能够说出3~5个HTML5新增布局和表单标签能够说出CSS3的新增特性有哪些 HTML5的新特性 HTML的新增特性主要是针对于以前的不足,增加了一些新的标签、新的表单和新的表单属性等。新特性都有兼容性问题,基本是IE9+以上版本......
  • Java SE 20 新增特性
    JavaSE20新增特性作者:Grey原文地址:博客园:JavaSE20新增特性CSDN:JavaSE20新增特性源码源仓库:Github:java_new_features镜像仓库:GitCode:java_new_featuresSwitch类型匹配(第四次预览)在JavaSE17新增特性中,Switch类型匹配作为预览功能推出,到JavaSE20,这个......
  • 【SpringBoot系列】四、SpringBoot特性_外部化配置(properties文件配置)
            SpringBoot允许将配置进行外部化(externalize),这样你就能够在不同的环境下使用相同的代码。你可以使用properties文件,yaml文件,环境变量和命令行参数来外部化配置。使用@Value注解,可以直接将属性值注入到beans中,然后通过Spring的Environment抽象或通过@ConfigurationP......
  • 【SpringBoot系列】三、SpringBoot特性_SpringApplication类(自定义Banner)
        SpringApplication类作为SpringBoot最基本、最核心的类,在main方法中用来启动SpringBoot项目。一般情况下,只需在main方法中使用SpringApplication.run静态方法来启动项目:packagecom.xcbeyond.springboot;importorg.springframework.boot.SpringApplication;importorg.......