文章目录
- `Lambda表达式`
- Lambda表达式的基本语法
- 示例
- 函数接口
- 参数与类型推断
- 函数式接口的预定义类型
- `自定义函数接口`
- 例子
- `分类`
- 消费型接口(Consumer)
- 供给型接口(Supplier)
- 函数型接口(Function)
- 断言型接口(Predicate)
- 运算型接口(UnaryOperator)
- 动作型接口(Runnable)
- `消费型`
- `供给型`
- `函数型`
- `断言型`
- `方法和构造器引用`
- 方法引用(Method Reference):
- 构造器引用(Constructor Reference):
- 示例:
- `streamAPI`
- 创建流
- 1. 从集合创建流:
- 2. 从数组创建流:
- 3. 使用Stream.of创建流:
- 4. 通过生成流的方式:
- a. 使用 Stream.iterate:
- b. 使用 Stream.generate:
- 5. 从文件创建流:
- 6. 使用特殊值创建流:
- 中间操作
- 1. **Filter(过滤):**
- 2. **Map(映射):**
- 3. **FlatMap(扁平映射):**
- 4. **Distinct(去重):**
- 5. **Sorted(排序):**
- 6. **Peek(查看):**
- 终止操作
- 1. **forEach(遍历):**
- 2. **count(计数):**
- 3. **collect(收集):**
- 4. **reduce(归约):**
- 5. **anyMatch、allMatch、noneMatch(匹配):**
- 6. **min、max(最小值、最大值):**
- Optional 类
- 创建 Optional 对象:
- 获取值:
- 判断是否包含值:
- 使用 map 处理值:
- 使用过滤器过滤值:
- 使用 flatMap 处理嵌套的 Optional:
Lambda表达式
Lambda表达式是Java 8引入的一项重要特性,它为Java语言引入了函数式编程的概念。Lambda表达式使得代码更为简洁、可读,并且支持更灵活的编程方式。下面是Lambda表达式的一些详细信息:
Lambda表达式的基本语法
Lambda表达式的基本语法如下:
(parameters) -> expression
或者
(parameters) -> { statements; }
parameters
:参数列表,类似于方法的参数列表,可以为空或非空。->
:Lambda运算符,分隔参数列表和Lambda表达式的主体。expression
:Lambda表达式的执行体,可以是单个表达式。{ statements; }
:Lambda表达式的执行体,可以是一个代码块,包含多个语句。
示例
下面是一个简单的Lambda表达式示例,实现了一个简单的函数接口:
// 使用匿名内部类
Runnable runnable1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello from anonymous class!");}
};// 使用Lambda表达式
Runnable runnable2 = () -> System.out.println("Hello from Lambda!");// 调用
runnable1.run();
runnable2.run();
函数接口
Lambda表达式需要与函数接口(Functional Interface)一起使用。函数接口是只包含一个抽象方法的接口,可以使用@FunctionalInterface
注解来确保它是函数接口。Lambda表达式可以与任何函数接口匹配。
@FunctionalInterface
interface MyFunctionalInterface {void myMethod();
}MyFunctionalInterface myLambda = () -> System.out.println("Hello from Lambda!");// 调用
myLambda.myMethod();
参数与类型推断
Lambda表达式可以自动推断参数的类型,也可以省略参数的类型声明。例如:
// 无参数的Lambda表达式
() -> System.out.println("Hello");// 单参数的Lambda表达式
x -> x * x;// 多参数的Lambda表达式
(x, y) -> x + y;
函数式接口的预定义类型
Java 8引入了一些预定义的函数式接口,如Consumer
、Predicate
、Function
等。这些接口可以用于Lambda表达式的参数类型。
// Consumer接口,接受一个参数,无返回值
Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase());// Predicate接口,接受一个参数,返回boolean值
Predicate<Integer> isEven = num -> num % 2 == 0;// Function接口,接受一个参数,返回一个结果
Function<Integer, String> intToString = num -> String.valueOf(num);
Lambda表达式是Java 8引入的一个强大功能,它使得编写函数式风格的代码更为容易。通过使用Lambda表达式,可以实现更简洁、清晰、灵活的代码。
自定义函数接口
在Java中,可以通过自定义接口并使用@FunctionalInterface
注解来创建自定义的函数接口。一个函数接口只能有一个抽象方法,但可以包含多个默认方法或静态方法。下面是一个简单的自定义函数接口的例子:
@FunctionalInterface
interface MyCustomFunctionalInterface {// 抽象方法void myMethod();// 默认方法default void defaultMethod() {System.out.println("Default method in the interface");}// 静态方法static void staticMethod() {System.out.println("Static method in the interface");}
}
在上面的例子中:
MyCustomFunctionalInterface
是一个自定义的函数接口。myMethod
是该接口的抽象方法,只包含一个方法。defaultMethod
是一个默认方法,可以在接口中提供默认的实现。staticMethod
是一个静态方法,可以在接口中提供静态方法。
你可以使用这个自定义函数接口并通过Lambda表达式来实现其抽象方法:
MyCustomFunctionalInterface myLambda = () -> System.out.println("Hello from myMethod");// 调用抽象方法
myLambda.myMethod();// 调用默认方法
myLambda.defaultMethod();// 调用静态方法
MyCustomFunctionalInterface.staticMethod();
这样,你就创建了一个自定义的函数接口,并通过Lambda表达式实现了它的抽象方法。这种方式使得你能够定义自己的函数式接口,以便在项目中更灵活地使用Lambda表达式。
例子
当你需要执行某种操作时,你可以定义一个适合Lambda表达式的自定义函数接口。下面是一个简单的例子,假设你想要定义一个能够执行两个整数相加的函数接口:
@FunctionalInterface
interface MyAddition {int add(int a, int b);
}
这是一个非常简单的函数接口,只有一个抽象方法 add
,接受两个整数参数并返回它们的和。现在,你可以使用这个自定义函数接口来创建Lambda表达式,并执行加法操作:
public class CustomFunctionalInterfaceExample {public static void main(String[] args) {// 使用Lambda表达式实现加法操作MyAddition addition = (a, b) -> a + b;// 调用add方法int result = addition.add(5, 3);System.out.println("Result: " + result);}
}
在这个例子中,MyAddition
函数接口充当了一个加法操作的定义,Lambda表达式 (a, b) -> a + b
实现了 add
方法的具体逻辑。最后,通过调用 add
方法,你可以得到两个整数的和,并输出结果。这是一个简单的例子,但它展示了如何创建和使用自定义的函数接口。
分类
函数式接口可以分为几个主要的类别,这些类别基于接口中的抽象方法数量和签名。在Java中,函数式接口通常用于支持Lambda表达式。以下是一些常见的函数式接口分类:
-
消费型接口(Consumer):
- 描述:接受一个参数,但没有返回值。
- 示例:
Consumer<T>
。
-
供给型接口(Supplier):
- 描述:不接受任何参数,但有返回值。
- 示例:
Supplier<T>
。
-
函数型接口(Function):
- 描述:接受一个参数,并返回一个结果。
- 示例:
Function<T, R>
。
-
断言型接口(Predicate):
- 描述:接受一个参数,并返回一个布尔值。
- 示例:
Predicate<T>
。
-
运算型接口(Operator):
- 描述:接受一个参数,进行一些操作,并返回结果(通常用于修改输入参数)。
- 示例:
UnaryOperator<T>
(一元运算符),BinaryOperator<T>
(二元运算符)。
-
功能组合接口:
- 描述:组合了多个基本函数接口,通常用于构建更复杂的操作。
- 示例:
BiFunction<T, U, R>
(接受两个参数并返回结果),UnaryOperator<T>
(一元运算符)等。
-
动作型接口(Runnable、Callable等):
- 描述:通常不接受参数或者参数没有语义上的意义,也没有返回值。
- 示例:
Runnable
,Callable<T>
。
-
特化的函数式接口:
- 描述:Java 8引入了一系列特化的函数式接口,如
IntConsumer
,LongFunction<R>
等,用于处理特定的数据类型,避免装箱拆箱的性能开销。
- 描述:Java 8引入了一系列特化的函数式接口,如
示例代码:
// Consumer接口
Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase());// Supplier接口
Supplier<Integer> randomNumber = () -> (int) (Math.random() * 100);// Function接口
Function<Integer, String> intToString = num -> String.valueOf(num);// Predicate接口
Predicate<Integer> isEven = num -> num % 2 == 0;// UnaryOperator接口
UnaryOperator<Integer> square = x -> x * x;// BinaryOperator接口
BinaryOperator<Integer> add = (a, b) -> a + b;
这些接口提供了不同类型的操作,使得在使用Lambda表达式时更加灵活和方便。选择适当的函数式接口取决于你希望执行的操作的特性。
好的,我将为你提供一些Lambda表达式的练习,涵盖不同类型的函数式接口。每个练习都有一个简单的任务,你可以使用Lambda表达式来实现。请注意,这些练习旨在帮助你熟悉Lambda表达式的不同应用场景。
消费型接口(Consumer)
- 创建一个
Consumer<String>
,用于打印字符串的大写形式。
Consumer<String> printUpperCase = // Lambda表达式实现
printUpperCase.accept("hello"); // 输出: HELLO
供给型接口(Supplier)
- 创建一个
Supplier<Integer>
,用于生成一个随机整数。
Supplier<Integer> randomNumber = // Lambda表达式实现
int number = randomNumber.get();
System.out.println("Random Number: " + number);
函数型接口(Function)
- 创建一个
Function<Integer, String>
,将整数转换为对应的星期几字符串。
Function<Integer, String> intToDay = // Lambda表达式实现
String day = intToDay.apply(1); // 输出: Monday
断言型接口(Predicate)
- 创建一个
Predicate<String>
,判断字符串是否为空。
Predicate<String> isNullOrEmpty = // Lambda表达式实现
boolean result = isNullOrEmpty.test("Hello");
System.out.println("Is Null or Empty: " + result); // 输出: false
运算型接口(UnaryOperator)
- 创建一个
UnaryOperator<Integer>
,用于计算一个整数的平方。
UnaryOperator<Integer> square = // Lambda表达式实现
int result = square.apply(5); // 输出: 25
动作型接口(Runnable)
- 创建一个
Runnable
,用于在控制台打印一条简单的消息。
Runnable printMessage = // Lambda表达式实现
printMessage.run(); // 输出: Hello, Lambda!
这些练习旨在帮助你练习不同类型的函数式接口的使用,以及如何使用Lambda表达式来简化代码。完成这些练习后,你应该对Lambda表达式在不同场景下的应用有更好的理解。
消费型
在Java 8中,消费型接口通常是指只接受参数而没有返回值的函数接口。一个常见的例子是Consumer
接口。以下是一个简单的Java 8消费型接口练习示例:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;public class ConsumerExample {public static void main(String[] args) {// 创建一个字符串列表List<String> languages = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 使用forEach方法遍历列表,并使用Consumer接口打印每个元素System.out.println("Printing elements using Consumer:");forEachWithConsumer(languages, (String language) -> {System.out.println(language);});// 使用匿名内部类实现Consumer接口System.out.println("\nPrinting elements using anonymous class:");forEachWithConsumer(languages, new Consumer<String>() {@Overridepublic void accept(String language) {System.out.println(language);}});}// 使用Consumer接口的forEach方法来遍历列表private static <T> void forEachWithConsumer(List<T> list, Consumer<T> consumer) {for (T element : list) {consumer.accept(element);}}
}
在这个示例中,我们创建了一个字符串列表(languages
),然后使用forEachWithConsumer
方法遍历列表,并通过Consumer
接口打印每个元素。可以看到,通过Lambda表达式或匿名内部类,我们可以方便地传递不同的消费型接口实现来执行不同的操作。
供给型
在Java 8中,供给型接口通常是指无参数但有返回值的函数接口。一个常见的例子是Supplier
接口。以下是一个简单的Java 8供给型接口练习示例:
import java.util.function.Supplier;public class SupplierExample {public static void main(String[] args) {// 使用Supplier接口生成随机数Supplier<Double> randomNumberSupplier = () -> Math.random();// 打印生成的随机数System.out.println("Random Number: " + randomNumberSupplier.get());// 使用Supplier接口生成当前时间戳Supplier<Long> currentTimeSupplier = System::currentTimeMillis;// 打印当前时间戳System.out.println("Current Time: " + currentTimeSupplier.get());}
}
在这个示例中,我们首先创建了一个Supplier
接口的实现,通过Lambda表达式生成一个随机数。然后,我们使用get
方法获取随机数的值并打印出来。
接着,我们创建另一个Supplier
接口的实现,这次使用方法引用(System::currentTimeMillis
)来获取当前时间戳。同样,我们通过get
方法获取当前时间戳的值并打印出来。
这个示例演示了如何使用供给型接口来生成不同类型的值,可以根据实际需求自定义Supplier
接口的实现。
函数型
在Java 8中,函数型接口是指只有一个抽象方法的接口,可以使用Lambda表达式来实现。java.util.function
包中提供了许多内置的函数型接口,比如Function
、Predicate
、UnaryOperator
等。以下是一个简单的Java 8函数型接口练习示例:
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;public class FunctionInterfaceExample {public static void main(String[] args) {// 使用Function接口将字符串转为大写Function<String, String> toUpperCaseFunction = str -> str.toUpperCase();String inputString = "hello world";// 打印转换前的字符串System.out.println("Original String: " + inputString);// 使用Function接口转换字符串为大写String upperCaseString = toUpperCaseFunction.apply(inputString);// 打印转换后的字符串System.out.println("Upper Case String: " + upperCaseString);// 使用Predicate接口判断一个数字是否为正数Predicate<Integer> isPositive = num -> num > 0;int number = 42;// 判断数字是否为正数System.out.println("Is " + number + " positive? " + isPositive.test(number));// 使用UnaryOperator接口对一个数字进行平方操作UnaryOperator<Integer> square = x -> x * x;int originalNumber = 7;// 打印平方前的数字System.out.println("Original Number: " + originalNumber);// 使用UnaryOperator接口进行平方操作int squaredNumber = square.apply(originalNumber);// 打印平方后的数字System.out.println("Squared Number: " + squaredNumber);}
}
在这个示例中,我们使用了Function
接口将字符串转为大写,Predicate
接口判断一个数字是否为正数,以及UnaryOperator
接口对一个数字进行平方操作。通过Lambda表达式实现了这些接口的抽象方法。函数型接口的使用使得代码更为简洁和灵活。
断言型
在Java 8中,断言型接口通常是指具有布尔类型返回值的函数接口,主要用于在代码中进行条件判断。一个常见的例子是Predicate
接口。以下是一个简单的Java 8断言型接口练习示例:
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;public class PredicateExample {public static void main(String[] args) {// 创建一个整数列表List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 使用Predicate接口判断数字是否为偶数,并打印结果System.out.println("Even numbers:");evaluate(numbers, (Integer number) -> number % 2 == 0);// 使用Predicate接口判断数字是否大于 5,并打印结果System.out.println("\nNumbers greater than 5:");evaluate(numbers, (Integer number) -> number > 5);}// 使用Predicate接口的test方法来进行条件判断private static <T> void evaluate(List<T> list, Predicate<T> predicate) {for (T element : list) {if (predicate.test(element)) {System.out.print(element + " ");}}}
}
在这个示例中,我们创建了一个整数列表(numbers
),然后使用 evaluate
方法通过 Predicate
接口进行条件判断。首先,我们使用 Predicate
接口判断数字是否为偶数,然后判断数字是否大于 5。在 evaluate
方法中,我们通过调用 predicate.test(element)
执行断言,如果返回 true
,则打印相应的元素。
这个示例演示了如何使用断言型接口来进行灵活的条件判断,可以根据实际需求自定义 Predicate
接口的实现。
方法和构造器引用
在Java 8中,方法引用和构造器引用是Lambda表达式的一种简化形式,用于更简洁地表示特定类型的函数式接口的实现。它们提供了一种更紧凑的语法,以便更清晰地表达代码的意图。
方法引用(Method Reference):
方法引用允许你通过方法的名称来引用它。它提供了一种简化Lambda表达式的方式,可以用更紧凑的语法来调用已经存在的方法。
有四种主要的方法引用形式:
-
静态方法引用:
// 例如,假设有一个静态方法 ClassName::staticMethodName;
-
实例方法引用:
// 例如,假设有一个实例方法,通过对象实例引用 instance::instanceMethodName;
-
类名引用一个实例方法:
// 例如,假设有一个实例方法,通过类名引用,适用于静态上下文 ClassName::instanceMethodName;
-
类名引用一个构造方法:
// 例如,通过类名引用构造方法 ClassName::new;
构造器引用(Constructor Reference):
构造器引用是一种特殊的方法引用,用于通过构造方法创建新对象。
构造器引用的语法如下:
ClassName::new;
这将引用 ClassName
类的构造方法,用于创建新的对象。
示例:
以下是一个使用方法引用和构造器引用的简单示例:
import java.util.Arrays;
import java.util.List;class Person {String name;Person(String name) {this.name = name;}static void printName(Person person) {System.out.println(person.name);}
}public class MethodAndConstructorReferenceExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用静态方法引用names.forEach(Person::printName);// 使用构造器引用List<Person> persons = Arrays.asList(new Person("Alice"),new Person("Bob"),new Person("Charlie"));persons.forEach(Person::printName);}
}
在上面的例子中,Person::printName
是一个静态方法引用,Person::new
是一个构造器引用。这两种引用形式都使代码更加简洁、易读。
streamAPI
创建流
Java 8引入了流(Stream)的概念,它是一种用于处理集合数据的新抽象。流允许你通过一系列的操作来处理集合,这些操作可以是中间操作或终端操作。
以下是如何创建流的一些方法:
1. 从集合创建流:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 从集合创建流
Stream<String> streamFromList = myList.stream();
2. 从数组创建流:
String[] array = {"Java", "Python", "JavaScript", "C#", "Ruby"};// 从数组创建流
Stream<String> streamFromArray = Arrays.stream(array);
3. 使用Stream.of创建流:
Stream<String> streamOfValues = Stream.of("Java", "Python", "JavaScript", "C#", "Ruby");
4. 通过生成流的方式:
a. 使用 Stream.iterate:
// 从0开始,每次加2,生成无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
b. 使用 Stream.generate:
// 生成5个随机数的流
Stream<Double> randomNumbers = Stream.generate(Math::random).limit(5);
5. 从文件创建流:
// 从文件创建流,每行作为流的元素
Path filePath = Paths.get("path/to/file.txt");
Stream<String> lines = Files.lines(filePath);
6. 使用特殊值创建流:
// 创建空流
Stream<String> emptyStream = Stream.empty();// 创建包含单个元素的流
Stream<String> singleElementStream = Stream.of("Java");// 创建包含重复元素的流
Stream<String> repeatedElementStream = Stream.generate(() -> "Java").limit(5);
这些是一些创建流的基本方法。创建流后,你可以使用各种中间操作和终端操作来对流进行处理。例如,filter
、map
、flatMap
是一些中间操作,而 forEach
、collect
、reduce
是一些终端操作。
中间操作
中间操作是在流上执行的操作,这些操作不会产生最终的结果,而是返回一个新的流,以便可以将多个中间操作链接在一起。以下是一些中间操作的示例:
1. Filter(过滤):
过滤操作通过给定的条件过滤流中的元素:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 过滤出长度大于3的元素
Stream<String> filteredStream = myList.stream().filter(s -> s.length() > 3);
2. Map(映射):
映射操作用于对流中的每个元素应用函数:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 将每个字符串转换为大写
Stream<String> upperCaseStream = myList.stream().map(String::toUpperCase);
3. FlatMap(扁平映射):
flatMap
将每个元素映射为一个流,然后将这些流连接成一个流:
List<List<Integer>> numbers = Arrays.asList(Arrays.asList(1, 2, 3),Arrays.asList(4, 5, 6),Arrays.asList(7, 8, 9)
);// 将嵌套列表平铺成一个流
Stream<Integer> flatMapStream = numbers.stream().flatMap(List::stream);
4. Distinct(去重):
去重操作用于移除流中的重复元素:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby", "Java");// 去除重复元素
Stream<String> distinctStream = myList.stream().distinct();
5. Sorted(排序):
排序操作用于对流中的元素进行排序:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 对元素按字母顺序排序
Stream<String> sortedStream = myList.stream().sorted();
6. Peek(查看):
peek
操作用于查看流中的元素,常用于调试:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 打印每个元素并返回原始流
Stream<String> peekStream = myList.stream().peek(System.out::println);
这些中间操作允许你以流畅的方式对数据进行转换和处理,创建一个由多个操作链接而成的流水线。最终,通过终端操作,你可以获取结果或触发流的处理。
终止操作
终端操作是流操作的最终步骤,它们会触发流的处理,并产生一个最终的结果或副作用。以下是一些终端操作的示例:
1. forEach(遍历):
forEach
用于遍历流中的元素:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 遍历并打印每个元素
myList.stream().forEach(System.out::println);
2. count(计数):
count
用于计算流中的元素数量:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 计算流中的元素数量
long count = myList.stream().count();
System.out.println("Number of elements: " + count);
3. collect(收集):
collect
用于将流中的元素收集到一个集合或其他数据结构中:
List<String> myList = Arrays.asList("Java", "Python", "JavaScript", "C#", "Ruby");// 将元素收集到一个列表中
List<String> collectedList = myList.stream().collect(Collectors.toList());
4. reduce(归约):
reduce
用于将流中的元素归约为一个值:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 将元素相加,得到总和
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
System.out.println("Sum: " + sum.orElse(0));
5. anyMatch、allMatch、noneMatch(匹配):
这些操作用于检查流中的元素是否匹配给定的条件:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 是否存在大于3的元素
boolean anyGreaterThanThree = numbers.stream().anyMatch(n -> n > 3);// 是否所有元素都大于3
boolean allGreaterThanThree = numbers.stream().allMatch(n -> n > 3);// 是否不存在小于0的元素
boolean noneLessThanZero = numbers.stream().noneMatch(n -> n < 0);
6. min、max(最小值、最大值):
min
和 max
用于获取流中的最小值和最大值:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 获取最小值
Optional<Integer> min = numbers.stream().min(Integer::compareTo);// 获取最大值
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
这些是一些常见的终端操作,它们用于触发流的处理并生成最终的结果或副作用。在使用流时,选择适当的终端操作取决于你的具体需求。
Optional 类
Optional
类是 Java 8 引入的一个用于处理可能为 null
的值的容器类。它旨在减少在代码中出现的 null
引用,以避免空指针异常。
Optional
类的主要目标是通过显式声明一个值可能为空,从而鼓励程序员更加谨慎地处理可能为 null
的情况,以减少空指针异常的风险。
以下是 Optional
类的一些基本用法:
创建 Optional 对象:
-
of 方法:
Optional<String> optionalValue = Optional.of("Hello, World!");
-
ofNullable 方法:
String value = // some value, may be null Optional<String> optionalValue = Optional.ofNullable(value);
-
empty 方法:
Optional<String> emptyOptional = Optional.empty();
获取值:
-
get 方法:
Optional<String> optionalValue = Optional.of("Hello, World!"); String value = optionalValue.get();
注意:使用
get
方法时,如果Optional
包含了null
值,将抛出NoSuchElementException
。 -
orElse 方法:
Optional<String> optionalValue = Optional.ofNullable(null); String result = optionalValue.orElse("Default Value");
如果
optionalValue
为null
,则返回指定的默认值。 -
orElseGet 方法:
Optional<String> optionalValue = Optional.ofNullable(null); String result = optionalValue.orElseGet(() -> generateDefaultValue());
如果
optionalValue
为null
,则通过orElseGet
方法中提供的Supplier
生成默认值。
判断是否包含值:
Optional<String> optionalValue = Optional.of("Hello, World!");// 判断是否包含值
boolean hasValue = optionalValue.isPresent();
使用 map 处理值:
Optional<String> optionalValue = Optional.of("Hello, World!");// 如果值存在,将其转换为大写
Optional<String> upperCaseValue = optionalValue.map(String::toUpperCase);
使用过滤器过滤值:
Optional<String> optionalValue = Optional.of("Hello, World!");// 过滤值,只有满足条件的值才会保留
Optional<String> filteredValue = optionalValue.filter(value -> value.contains("Hello"));
使用 flatMap 处理嵌套的 Optional:
Optional<String> optionalValue = Optional.of("Hello, World!");// 如果值存在,将其转换为大写,然后使用 flatMap 处理嵌套的 Optional
Optional<String> result = optionalValue.flatMap(value -> Optional.ofNullable(value.toUpperCase()));
Optional
类提供了一种更安全、更规范的处理可能为 null
的值的方式。在编写代码时,考虑使用 Optional
可以提高代码的可读性和可维护性。