目录
函数式接口
自定义函数式接口
1.定义一个抽象方法:接口中只能有一个抽象方法
2.在接口上标记 @FunctionalInterface 注解后,编辑器就能自动检测自定义函数式接口是否存在问题,也可以不标记。
内置的函数式接口
java内置了4个核心函数式接口:
1. Comsumer<T> 消费型接口:表示接受单个输入参数但不返回结果的操作,包含方法: void accept(T t) ,可以理解为消费者,只消费(接受单个参数),不返回(返回为 void)
2. Supplier<T> 供给型接口:表示结果的供给者,包含方法 T get() ,可以理解为供给者,只提供(返回 T 类型对象)、不消费(不接受参数)
3. Function<T, R>
函数型接口:表示接受一个 T
类型参数并返回 R
类型结果的对象,包含方法 R apply(T t)
4. Predicate<T>
断言型接口:确定 T
类型的对象是否满足约束,并返回 boolean
值,包含方法 boolean test(T t)
Comsumer<T> 实例:
import java.util.function.Consumer;
public class TestFunctionInterface1 {
public static void main(String[] args) {
/**
* Consumer<String> consumer=new Consumer<String>() {
* @Override
* public void accept(String s) {
* System.out.println(s);
* }
* };
* consumer.accept("只消费,不返回");
* */
Consumer<String> consumer=s -> System.out.println(s);
consumer.accept("只消费,不返回");
}
}
运行结果:
只消费,不返回
Supplier<T> 实例:
import java.util.function.Supplier;
public class TestFunctionInterface1 {
public static void main(String[] args) {
/**
* Supplier<String> supplier=new Supplier<String>() {
* @Override
* public String get() {
* return "只返回,不消费";
* }
* };
* String s=supplier.get();
* System.out.println(s);
* */
Supplier<String> supplier=() -> "只返回,不消费"; //return可省略不写
String s=supplier.get();
System.out.println(s);
}
}
运行结果:
只返回,不消费
Predicate<T> 实例:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class TestPredicate {
public static List<String> filterStringList(List<String> list, Predicate<String> predicate){
//过滤后的字符串列表
ArrayList<String> arrayList=new ArrayList<>();
for (String string:list){
if (predicate.test(string)){
//如果 test 是 true,则将元素加入到过滤后的列表中
arrayList.add(string);
}
}
return arrayList;
}
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<>();
arrayList.add("Java");
arrayList.add("PHP");
arrayList.add("Python");
arrayList.add("JavaScript");
System.out.println("过滤前:");
System.out.println(arrayList);
// List<String> filterResult=filterStringList(arrayList, new Predicate<String>() {
// @Override
// public boolean test(String s) {
// return s.contains("P");
// }
// });
List<String> filterResult=filterStringList(arrayList,s -> s.contains("P"));
System.out.println("过滤后:");
System.out.println(filterResult);
}
}
运行结果:
过滤前:
[Java, PHP, Python, JavaScript]
过滤后:
[PHP, Python]
方法引用
对象引用实例方法
System.out 就是对象,而 println 就是实例方法
实例:
import java.util.function.Consumer;
public class TestMethodReference {
public static void main(String[] args) {
// Consumer<String> consumer = s -> System.out.println(s);
Consumer<String> consumer = System.out::println;
consumer.accept("这只是个测试");
}
}
运行结果:
这只是个测试
类引用静态方法
实例:
import java.util.Comparator;
import java.util.function.Function;
public class TestMethodReference {
public static void main(String[] args) {
//使用Lambda表达式
Comparator<Integer> comparator1 = (t1,t2) -> Integer.compare(t1,t2);
System.out.println(comparator1.compare(11,12));
//使用方法引用,类::静态方法( compare() 为静态方法
Comparator<Integer> comparator2=Integer::compare;
System.out.println(comparator2.compare(12,11));
// 使用 Lambda 表达式
Function<Double, Long> function1 = d -> Math.round(d);
Long apply1 = function1.apply(1.0);
System.out.println(apply1);
// 使用方法引用,类 :: 静态方法( round() 为静态方法)
Function<Double, Long> function2 = Math::round;
Long apply2 = function2.apply(2.0);
System.out.println(apply2);
}
}
运行结果:
-1
1
1
2
查看 Java 源码,可观察到 compare() 和 round() 方法都是静态方法:
类引用实例方法
当函数式接口中的抽象方法有两个参数时,已实现方法的第 1 个参数作为方法调用者时,也可以使用方法引用。此时,就可以使用类来引用实例方法了(即实例中的String::compareTo
)
实例:
import java.util.Comparator;
public class TestMethodReference {
public static void main(String[] args) {
//使用匿名内部类
Comparator<String> comparator0=new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
int compare0 = comparator0.compare("YES","NO");
//compareTo() 如果调用该方法的字符串对象按字典顺序在参数字符串之后,那么返回一个正整数
System.out.println(compare0);
// 使用 Lambda 表达式
Comparator<String> comparator1 = (s1, s2) -> s1.compareTo(s2);
int compare1 = comparator1.compare("Hello", "Java");
//compareTo() 如果调用该方法的字符串对象按字典顺序在参数字符串之前,那么返回一个负整数
System.out.println(compare1);
// 使用方法引用,类 :: 实例方法( compareTo() 为 String 类的实例方法)
Comparator<String> comparator2 = String::compareTo;
int compare2 = comparator2.compare("Hello", "Hello");
//compareTo() 如果两个字符串相等,那么返回 0
System.out.println(compare2);
}
}
运行结果:
11
-2
0
类引用构造方法
实例:
import java.util.function.Function;
import java.util.function.Supplier;
public class TestMethodReference {
static class Person{
private String name;
public Person(){
System.out.println("无参数构造方法执行了");
}
public Person(String name){
System.out.println("单参数构造方法执行了");
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) {
//使用 Lambda 表达式,调用无参构造方法
Supplier<Person> supplier1 = () -> new Person();
supplier1.get();
//使用方法引用,调用无参构造方法
Supplier<Person> supplier2 = Person::new;
supplier2.get();
//使用 Lambda 表达式,调用单参数构造方法
Function<String,Person> function1 = name -> new Person(name);
Person person1 = function1.apply("小慕");
System.out.println(person1.getName());
//使用方法引用,调用单参数构造方法
Function<String,Person> function2 = Person::new;
Person person2 = function2.apply("小明");
System.out.println(person2.getName());
}
}
运行结果:
无参数构造方法执行了
无参数构造方法执行了
单参数构造方法执行了
小慕
单参数构造方法执行了
小明
流式操作
Stream 对象的创建
通过集合创建Stream
串行流并行流的区别是:串行流从集合中取数据是按照集合的顺序的;而并行流是并行操作的,获取到的数据是无序的
// 创建一个集合,并添加几个元素
List<String> stringList = new ArrayList<>();
stringList.add("hello");
stringList.add("world");
stringList.add("java");
// 通过集合获取串行 stream 对象
Stream<String> stream = stringList.stream();
// 通过集合获取并行 stream 对象
Stream<String> personStream = stringList.parallelStream();
通过数组创建Stream
// 初始化一个整型数组
int[] arr = new int[]{1,2,3};
// 通过整型数组,获取整形的 stream 对象
IntStream stream1 = Arrays.stream(arr);
// 通过字符串类型的数组,获取泛型类型为 String 的 stream 对象
String[] stringArr = new String[]{"Hello", "imooc"};
Stream<String> stream2 = Arrays.stream(stringArr);
通过 Stream 的 of() 方法
// 通过 Stream 类下的 of() 方法,创建 stream 对象、
Stream<Integer> stream = Stream.of(1, 2, 3);
创建无限流
1.使用 Stream.iterate() 方法:这个方法允许你从一个种子值开始,并应用一个一元操作符来生成一个无限流。并且,你可以通过调用 limit() 方法来限制流中的元素数量,并通过 collect() 方法来终止流并收集结果。
实例:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStream {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.iterate(1000,i -> i / 2);
List<Integer> collect = integerStream.limit(15).collect(Collectors.toList());
int num=1;
for(int i : collect){
System.out.println("第" + num++ + "个元素为:" + i);
}
}
}
运行结果:
第1个元素为:1000
第2个元素为:500
第3个元素为:250
第4个元素为:125
第5个元素为:62
第6个元素为:31
第7个元素为:15
第8个元素为:7
第9个元素为:3
第10个元素为:1
第11个元素为:0
第12个元素为:0
第13个元素为:0
第14个元素为:0
第15个元素为:0
2.使用 Stream.generate() 方法:这个方法允许你通过提供一个 Supplier 接口来生成元素,从而创建一个无限流。UUID::randomUUID 是一个随机生成一串 UUID 码的方法引用,同样,通过调用 limit() 方法来限制流中的元素数量,并通过 forEach() 方法来遍历并输出流中的结果。
实例:
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TestStream {
public static void main(String[] args) {
Supplier<UUID> uuidSupplier1 = UUID::randomUUID;
Stream<UUID> uuidStream = Stream.generate(uuidSupplier1);
uuidStream.limit(10).forEach(System.out::println);
}
}
运行结果:
c0b19729-70ff-431a-8679-adb511c1f2d5
84277269-3d35-4d46-a741-2ac06a703a0a
7f3cdd33-8c5d-46ac-bb3d-fe43e0047565
80e57c15-3bf4-4da6-9ca6-e19c85b16467
914908fa-23f2-4793-88ae-0c66dc2ba37b
2cf64e8c-0a90-4268-a120-39a8300ec568
3c264ae6-0772-4e34-b563-1b51f3ee483b
4660f1a4-71b8-4c60-a3ea-01e0d4354931
ec1e9023-aecd-4fca-879c-efecf8503d63
822c65fa-be3f-4eb7-aeb1-a7a5358e43a5
Stream 的中间操作
筛选与切片
filter() 和 limit() 以及 skip() 的实例:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStream {
public static void main(String[] args) {
/************ limit()部分 *************/
//生成一个无限流,其中每个元素都是0-99之间的整数,并用 limit() 方法截取前10个元素
Stream<Integer> stream = Stream.generate(() -> (int)(Math.random() * 100)).limit(10);
//用 collect() 方法 终止流并获取集合
List<Integer> before = stream.collect(Collectors.toList());
System.out.println("原始元素有:");
for (int i : before){
System.out.print(i + " ");
}
System.out.println();
/************ filter()部分 *************/
//用集合的元素再创建一个新的串行流
Stream<Integer> recoverStream1 = before.stream();
//然后从流中筛选出大于15的元素,并用 collect() 方法 终止流并获取集合
List<Integer> after = recoverStream1.filter(i -> i > 15).collect(Collectors.toList());
System.out.println("筛选后:");
for (int i : after){
System.out.print(i + " ");
}
System.out.println();
/************ skip()部分 *************/
Stream<Integer> recoverStream2 = before.stream();
//跳过前2个元素
List<Integer> enough = recoverStream2.skip(2).collect(Collectors.toList());
System.out.println("跳过后:");
for (int i : enough){
System.out.print(i + " ");
}
System.out.println();
//跳过前11个元素,此时已经超出流原有的元素数量,所以返回空流,集合自然也是空集
Stream<Integer> recoverStream3 = before.stream();
List<Integer> notEnough = recoverStream3.skip(11).collect(Collectors.toList());
System.out.println("跳过后:");
if(notEnough.size()==0){
System.out.println("(空)");
}
}
}
运行结果:
原始元素有:
63 66 20 51 69 49 37 93 17 72
筛选后:
63 66 20 51 69 49 37 93 17 72
跳过后:
20 51 69 49 37 93 17 72
跳过后:
(空)
distinct() 的实例:
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public class TestStream {
static class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
//使用 distinct() 去除一个列表中重复的元素
List<Integer> list1 = Arrays.asList(1,2,1,1,5,3);
Set<Integer> result = list1.stream().distinct().collect(Collectors.toSet());
System.out.println(result);
//使用 distinct() 去除一个字符串列表中的重复字符
List<String> list2 = Arrays.asList("ant","orange","pencil","pencil","piano");
list2.stream().distinct().forEach(i -> System.out.print(i + " "));
System.out.println();
/* 使用 distinct() 去除一个对象列表中的重复对象,
默认使用 Object.equals() 方法来确定重复性,这个方法只能去除相同的对象,
按照不同的标准来判断元素是否重复,需要重写 equals() 和 hashCode() 方法
*/
Person person=new Person("Jack",10);
Person person1=person;
List<Person> list3 = Arrays.asList(
new Person("Mike",20),
new Person("Sarah",18),
new Person("Bill",10),
new Person("Jack",35),
new Person("Jack",35),
new Person("Jack",20),
person,
person1
);
List<Person> result2 = list3.stream().distinct().collect(Collectors.toList());
for (int i = 0; i < result2.size(); i++) {
System.out.println(result2.get(i).getName() + "," + result2.get(i).getAge());
}
}
}
运行结果:
[1, 2, 3, 5]
ant orange pencil piano
Mike,20
Sarah,18
Bill,10
Jack,35
Jack,20
Jack,10
映射
实例:
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public class TestStream {
public static void main(String[] args) {
//创建一个包含小写字母的字符串列表
List<String> stringList = Arrays.asList("apple","banana","cat","dog","egg");
//调用 map() 方法,将 String 下的 toUpperCase() 方法作为参数,这个方法会被应用到每个元素,映射成一个新元素,类型由泛型决定
Set<String> stringSet = stringList.stream().map(String::toUpperCase).collect(Collectors.toSet());
System.out.println("map() 的应用:");
System.out.println(stringSet);
//创建一个整型元素列表
List<Integer> integerList = Stream.iterate(1,i -> i + 2).limit(5).collect(Collectors.toList());
//调用 mapToDouble() 方法,将 Integer 下的 doubleValue() 方法作为参数,该方法会被应用到每个元素上,产生一个新的 DoubleStream
DoubleStream doubleStream = integerList.stream().mapToDouble(Integer::doubleValue);
System.out.println("mapToDouble() 的应用:");
doubleStream.forEach(System.out::println);
//调用 mapToLong() 方法,将 Integer 下的 longValue() 方法作为参数,该方法会被应用到每个元素上,产生一个新的 LongStream
LongStream longStream = integerList.stream().mapToLong(Integer::longValue);
System.out.println("mapToLong() 的应用:");
longStream.forEach(System.out::println);
/**
* flatMap 将每个字符串转换为一个新的字符流,然后将这些流“扁平化”为一个单一的字符流。
* chars() 方法用于将字符串转换为字符的索引流,然后 mapToObj 将索引转换为字符。
* 最后,我们使用 collect 来收集结果。
* */
List<String> strings = Arrays.asList("Hello","World");
List<Character> characters = strings.stream()
.flatMap(s -> s.chars().mapToObj(c -> (char)c))
.collect(Collectors.toList());
System.out.println("flatMap() 的应用:");
System.out.println(characters);
}
}
运行结果:
map() 的应用:
[APPLE, EGG, CAT, BANANA, DOG]
mapToDouble() 的应用:
1.0
3.0
5.0
7.0
9.0
mapToLong() 的应用:
1
3
5
7
9
flatMap() 的应用:
[H, e, l, l, o, W, o, r, l, d]
排序
实例:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class TestStream {
public static void main(String[] args) {
List<Integer> integerList1 = Arrays.asList(1,10,5,20,15,16);
//调用 sorted() 方法自然排序,并打印每个元素
List<Integer> integerList2 = integerList1.stream().sorted().collect(Collectors.toList());
System.out.println(integerList2);
//定制排序,实现数字从大到小的排序
List<Integer> integerList3 = integerList1.stream().sorted(
(i1, i2) -> -Integer.compare(i1,i2)
).collect(Collectors.toList());
System.out.println(integerList3);
}
}
运行结果:
[1, 5, 10, 15, 16, 20]
[20, 16, 15, 10, 5, 1]
Stream 的终止操作
匹配与查找
实例:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class TestStream {
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(1,10,5,20,15,16);
System.out.println("列表元素:" + integers);
// 使用 allMatch(Predicate p) 检查是否匹配所有元素,如果匹配,则返回 true;否则返回 false
boolean b1 = integers.stream().allMatch(integer -> integer > 0);
if (b1) {
System.out.println("列表中所有的元素都大于0");
} else {
System.out.println("列表中不是所有的元素都大于0");
}
// 使用 anyMatch(Predicate p) 检查是否至少匹配一个元素
boolean b2 = integers.stream().anyMatch(integer -> integer >= 20);
if (b2) {
System.out.println("列表中至少存在一个的元素大于等于20");
} else {
System.out.println("列表中不存在任何一个大于等于20的元素");
}
// 使用 noneMath(Predicate p) 检查是否没有匹配所有元素
boolean b3 = integers.stream().noneMatch(integer -> integer > 100);
if (b3) {
System.out.println("列表中不存在大于100的元素");
} else {
System.out.println("列表中存在大于100的元素");
}
// 使用 findFirst() 获取当前流中的第一个元素
Optional<Integer> first = integers.stream().findFirst();
System.out.println("列表中第一个元素为:" + first);
// 使用 findAny() 获取当前流中的任意元素
Optional<Integer> any = integers.stream().findAny();
System.out.println("列表中任意元素:" + any);
// 使用 count() 获取当前流中元素总数
long count = integers.stream().count();
System.out.println("列表中元素总数为" + count);
// 使用 max(Comparator c) 获取流中最大值
Optional<Integer> max = integers.stream().max(Integer::compare);
System.out.println("列表中最大值为" + max);
// 使用 min(Comparator c) 获取流中最小值
Optional<Integer> min = integers.stream().min(Integer::compare);
System.out.println("列表中最小值为" + min);
}
}
运行结果:
列表中的元素:[1, 10, 5, 20, 15, 16]
列表中所有的元素都大于0
列表中至少存在一个的元素大于等于20
列表中不存在大于100的元素
列表中第一个元素为:Optional[1]
列表中任意元素:Optional[1]
列表中元素总数为6
列表中最大值为Optional[20]
列表中最小值为Optional[1]
归约
实例:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class TestStream {
public static void main(String[] args) {
//创建一个整形列表
List<Integer> integerList = Arrays.asList(0,1,5,10,15,20);
/**
* 使用 reduce(T identity,BinaryOperator b) 计算列表中所有整数和
* 第一个参数是累积操作的初始值。
* 第二个参数是累积操作的函数,它接受两个参数,一个是累积的值(初始值或者上一次操作的结果),另一个是流中的下一个元素。
* * * * * * * * * * * * * * * * * * * * * * *
* 如果流中没有元素,reduce 操作会返回你提供的初始值。
* 如果流有元素但不能进行累积(例如,是一个空流),reduce 会抛出 NullPointerException
* 或者返回给定的初始值(取决于你提供的函数是否处理 null)
* */
Integer sum = integerList.stream().reduce(0, Integer::sum);
System.out.println(sum);
// 使用 reduce(BinaryOperator b) 计算列表中所有整数和,返回一个 Optional<T>
Optional<Integer> reduce = integerList.stream().reduce(Integer::sum);
System.out.println(reduce);
}
}
运行结果:
51
Optional[51]
收集
实例:
import java.util.*;
import java.util.stream.Collectors;
public class TestStream {
public static void main(String[] args) {
//创建一个整形列表
List<Integer> integers = Arrays.asList(0,1,5,10,15,20);
Set<Integer> integerSet1 = integers.stream().collect(Collectors.toSet());
System.out.println("使用 toSet() 方法收集的列表:");
System.out.println(integerSet1);
List<Integer> integerList1 = integers.stream().collect(Collectors.toList());
System.out.println("使用 toList() 方法收集的列表:");
System.out.println(integerList1);
System.out.println("使用 toCollection() 方法收集的列表:");
List<Integer> integerList2 = integers.stream().collect(Collectors.toCollection(ArrayList::new));
System.out.println("有序集合:" + integerList2);
Set<Integer> integerSet2 = integers.stream().collect(Collectors.toCollection(HashSet::new));
System.out.println("哈希无序集合:" + integerSet2);
Set<Integer> integerSet3 = integers.stream().collect(Collectors.toCollection(TreeSet::new));
System.out.println("树状无序集合:" + integerSet3);
Queue<Integer> integerQueue1 = integers.stream().collect(Collectors.toCollection(PriorityQueue::new));
System.out.println("队列:" + integerQueue1);
Collection<Integer> integerCollection = integers.stream().collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println("链式哈希无序集合:" + integerQueue1);
}
}
运行结果:
使用 toSet() 方法收集的列表:
[0, 1, 20, 5, 10, 15]
使用 toList() 方法收集的列表:
[0, 1, 5, 10, 15, 20]
使用 toCollection() 方法收集的列表:
有序集合:[0, 1, 5, 10, 15, 20]
哈希无序集合:[0, 1, 20, 5, 10, 15]
树状无序集合:[0, 1, 5, 10, 15, 20]
队列:[0, 1, 5, 10, 15, 20]
链式哈希无序集合:[0, 1, 5, 10, 15, 20]
Optional 类
创建 Optional 对象
实例:
import java.util.Optional;
public class TestOptional {
public static void main(String[] args) {
// 创建一个 StringBuilder 对象
StringBuilder string = new StringBuilder("我是一个字符串");
// 使用 Optional.of(T t) 方法,创建 Optional 对象,注意 T 不能为空:
Optional<StringBuilder> stringBuilderOptional = Optional.of(string);
System.out.println(stringBuilderOptional);
// 使用 Optional.empty() 方法,创建一个空的 Optional 对象:
Optional<Object> empty = Optional.empty();
System.out.println(empty);
// 使用 Optional.ofNullable(T t) 方法,创建 Optional 对象,注意 t 允许为空:
stringBuilderOptional = null;
Optional<Optional<StringBuilder>> stringBuilderOptional1 = Optional.ofNullable(stringBuilderOptional);
System.out.println(stringBuilderOptional1);
}
}
运行结果:
Optional[我是一个字符串]
Optional.empty
Optional.empty
常用方法
实例:
package com.imooc.springboot.study;
import java.util.NoSuchElementException;
import java.util.Optional;
public class TestOptional {
static class Category {
private String name;
public Category(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Category{" +
"name='" + name + '\'' +
'}';
}
}
static class Goods {
private String name;
private Category category;
public Goods() {
}
public Goods(String name, Category category) {
this.name = name;
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Good{" +
"name='" + name + '\'' +
", category=" + category +
'}';
}
}
/**
* 获取商品的分类名称(使用 Optional 类包装)
* @param goods 商品
* @return 分类名称
*/
static String getGoodsCategoryName(Goods goods) {
// 将商品实例包装入 Optional 类,创建 Optional<Goods> 对象
Optional<Goods> goodsOptional = Optional.ofNullable(goods);
//orElse(T other):如果有值则将其返回,否则返回指定的other 对象
Goods goods1 = goodsOptional.orElse(new Goods("默认商品", null));
// 此时 goods1 一定是非空,不会产生空指针异常
Category category = goods1.getCategory();
// 将分类实例包装入 Optional 类,创建 Optional<Category> 对象
Optional<Category> categoryOptional = Optional.ofNullable(category);
//orElseGet(Supplier<? extends T other>):如果有值则将其返回,否则返回由Supplier接口实现提供的对象
Category category1 = categoryOptional.orElseGet(() -> new Category("默认分类"));
// 此时 category1 一定是非空,不会产生空指针异常
return category1.getName();
}
public static void main(String[] args) {
// 实例化一个商品类
Goods goods = null;
// 获取商品的分类名称
String categoryName = getGoodsCategoryName(goods);
System.out.println(categoryName);
/**
* 如果 value 不为空,optionalValue 将包含一个值,orElseThrow 将返回该值。
* 如果 value 为空,optionalValue 将为空,orElseThrow 将抛出一个由我们指定的 IllegalStateException 异常。
* 这个异常可以根据你的需求进行替换,比如 NullPointerException、IllegalArgumentException 等。
* */
try {
Optional<String> optionalValue = Optional.ofNullable(null);
//判断是否包含对象
System.out.println(optionalValue.isPresent()?"包含":"不包含");
//ifPresent() 如果值存在,执行操作,否则不执行任何操作
optionalValue.ifPresent(System.out::println);
//get():如果调用对象包含值,返回该值,否则抛出异常
String result1 = optionalValue.get();
String result2 = optionalValue.orElseThrow(() -> new IllegalStateException("Value is NULL"));
}catch (IllegalStateException e){
System.out.println(e.getMessage());
}catch (NoSuchElementException e){
System.out.println("result1为空");
}
}
}
运行结果:
默认分类
不包含
result1为空