31. Java 8 中引入的 Stream API 有哪些用途?
Java 8 中引入的 Stream API 是一个强大的新特性,它提供了一种高效且易于使用的处理数据的方法。Stream API 的用途主要包括以下几个方面:
- 简化集合操作:Stream API 可以对集合对象进行复杂的查询、过滤、映射和归约等操作,而无需显式地编写复杂的循环语句。
- 提高性能:通过并行流(Parallel Streams),Stream API 支持在多核处理器上自动分配任务,以充分利用计算资源,提高处理大数据集的效率。
- 函数式编程:Stream API 与Lambda表达式结合,使得可以以一种声明式的方式进行数据处理,代码更加简洁,可读性和可维护性更强。
以下是Stream API的一些具体用途:
-
过滤(Filter):通过设定条件来过滤数据。
List<String> names = Arrays.asList("John", "Jane", "Doe"); List<String> filteredNames = names.stream().filter(name -> name.startsWith("J")).collect(Collectors.toList());
-
映射(Map):将流中的每一个元素通过给定的函数进行转换。
List<Integer> numbers = Arrays.asList(1, 2, 3); List<Integer> squares = numbers.stream().map(n -> n * n).collect(Collectors.toList());
-
归约(Reduce):将流中的多个元素组合成一个结果,如求和、求积等。
Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
-
遍历(ForEach):用于遍历每个元素并进行相应的操作。
numbers.stream().forEach(System.out::println);
-
匹配(Match):用于检查流中是否存在满足给定条件或所有元素是否满足给定条件的元素。
boolean anyStartsWithJ = names.stream().anyMatch(name -> name.startsWith("J")); boolean allStartsWithJ = names.stream().allMatch(name -> name.startsWith("J"));
-
排序(Sorted):用于对流中的元素进行排序。
List<String> sortedNames = names.stream().sorted().collect(Collectors.toList());
-
收集(Collect):将流转换成其他形式,如列表、集合、映射等。
Set<String> uniqueNames = names.stream().collect(Collectors.toSet());
通过这些用途,可以看出 Stream API 为Java开发者提供了一种高效、简洁且易于并行化的数据处理方式,极大地丰富了Java在数据处理方面的表现力。
32. 请解释 Java 8 中的 Lambda 表达式和函数式接口。
Java 8 引入的 Lambda 表达式是一个可用于表示匿名函数的语法结构,它可以简化代码编写并提高代码的可读性。Lambda 表达式与函数式接口紧密相关,因为它们通常被用于实现这些接口。
1)Lambda 表达式
Lambda 表达式的基本语法如下:
(parameters) -> expression
或
(parameters) -> { statements; }
- 参数:如果参数类型可以自动推导,那么可以省略类型声明。
- ->:箭头操作符,将参数和表达式分开。
- 表达式/代码块:如果只有一条语句,并且是返回语句,可以省略花括号。
以下是 Lambda 表达式的几个示例:
// 无参数,返回一个整数
() -> 42// 接受一个整数参数并返回其平方
x -> x * x// 接受两个整数参数并返回他们的和
(int x, int y) -> x + y// 接受两个字符串,返回较长的字符串
(String s1, String s2) -> s1.length() > s2.length() ? s1 : s2
2)函数式接口
函数式接口是只包含一个抽象方法的接口。它们可以用 Lambda 表达式来实现。Java 8 中引入了一个注解 @FunctionalInterface
来显式声明一个接口是函数式接口,但这不是必须的。
以下是函数式接口的例子:
@FunctionalInterface
interface MyFunctionalInterface {// 唯一的抽象方法int calculate(int x, int y);
}
可以用 Lambda 表达式实现上述接口:
MyFunctionalInterface add = (x, y) -> x + y;
3)Lambda 表达式与函数式接口的关系
Lambda 表达式通常用于实现函数式接口的实例。Java 编译器根据 Lambda 表达式的类型推导来确定哪个函数式接口应该被实现。
例如,Runnable
是一个只有一个抽象方法的函数式接口:
Runnable run = () -> System.out.println("Hello World!");
在这个例子中,编译器会推导出 () -> System.out.println("Hello World!");
实现了 Runnable
接口。
总结来说,Lambda 表达式允许以一种简洁、表达性强的方式实现单方法接口(函数式接口),从而增强了 Java 语言在处理高阶函数和集合操作时的表现力。
领【150 道精选 Java 高频面试题】请go公众号:码路向前 。