Java9为Stream API带来了一系列新特性,这些特性使得流的处理更加灵活和强大。这些新特性为Java的流处理提供了更强大的工具,使得在处理大量数据或进行复杂的数据转换时能够编写更加简洁和高效的代码。它们为开发者提供了更多的控制流生成的灵活性,以及处理流中数据的能力。
此外,Java 9还在其他方面对Stream API进行了优化和改进,这些改进可能涉及到性能的提升、API设计的改进以及与其他Java 9特性的更好集成等。这些增强特性使得Java的流处理更加符合现代编程的需求,并有助于开发者更高效地处理数据流。
下面我们来看一下Java 9中Stream API的增强特性。
Stream接口方法的添加
在Java9中Stream的接口上增加了四个方法:
- takeWhile(Predicate Interface)
- dropWhile(Predicate Interface)
- iterate
- ofNullable
takeWhile(Predicate Interface)
takeWhile(Predicate Interface)方法会处理流中所有的数据,直到条件predicate返回false为止。
该方法的原型如下:
default Stream<T> takeWhile(Predicate<? super T> predicate)
takeWhile示例:
package com.morris.java9;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class TakeWhileDemo {
public static void main(String[] args) {
// 使用 takeWhile一直取元素,直至遇到第一个小于5的元素才停止
List<Integer> result = Stream.of(1, 2, 3, 4, 5, 1, 7, 8, 9)
.takeWhile(n -> n < 5)
.collect(Collectors.toList());
System.out.println(result); // 输出: [1, 2, 3, 4]
}
}
运行结果如下:
[1, 2, 3, 4]
在这个示例中,我们有一个包含整数的列表。我们使用takeWhile
和一个谓词n -> n < 5
来取出所有小于5的元素。
输出结果是[1, 2, 3, 4]
,因为当遇到第一个不小于5的元素(即5)时,takeWhile停止取出元素。
dropWhile(Predicate Interface)
dropWhile(Predicate Interface) 则正好与takeWhile()
方法相反,dropWhile()方法用于丢弃输入流中的元素,直到遇到第一个不满足给定谓词的元素为止。然后,它会返回从该元素开始到流末尾的所有元素的流。
dropWhile()方法的原型如下:
default Stream<T> dropWhile(Predicate<? super T> predicate)
方法签名和dropWhile()简直一模一样,除了方法名不同外,但是,却是两个截然不同的逻辑。
dropWhile()的工作方式是:它遍历输入流中的元素,并对每个元素应用给定的谓词predicate。只要谓词predicate返回true,它就会继续丢弃元素。但是,一旦谓词predicate对某个元素返回false,它就会停止丢弃元素,并返回从该元素开始到流末尾的所有元素的流。
dropWhile示例:
package com.morris.java9;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DropWhileDemo {
public static void main(String[] args) {
// 使用 dropWhile 取出元素并丢弃,直至所第一个大于等于5的才开始保留
List<Integer> result = Stream.of(1, 2, 3, 4, 5, 1, 5, 7, 8, 9)
.dropWhile(n -> n < 5)
.collect(Collectors.toList());
System.out.println(result); // 输出: [5, 1, 5, 7, 8, 9]
}
}
运行结果如下:
[5, 1, 5, 7, 8, 9]
iterate()
iterate()会循环遍历流中的数据,直到条件返回false时停止。
该方法的原型如下:
// Java8
static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
// Java9
static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
看方法原型,是不是很像for()循环语句,第一个参数seed表示初始化循环变量,第二个参数hasNext则为循环终止条件,第三个参数next则用于生成下一个循环值。
iterate()示例:
package com.morris.java9;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamIteratorDemo {
public static void main(String[] args) {
// 取出100以内的斐波那契数列数字
List<Integer> result = Stream.iterate(new int[]{0, 1}, t -> t[1] < 100, t -> new int[]{t[1], t[0] + t[1]} )
.map(t -> t[1])
.collect(Collectors.toList());
System.out.println(result); // 输出: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
}
}
运行结果如下:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
在这个示例中,我们从数组{0, 1}
开始,然后根据斐波那契数列的定义生成新的数组{arr[1], arr[0] + arr[1]}
。通过限制数组的第二个元素小于100,并取出每个数组的第一个元素,我们最终打印出了斐波那契数列的100以内的数字。
使用三个参数版本的Stream.iterate()方法可以更灵活地控制流的生成过程,同时也可以添加终止条件来避免无限循环。
ofNullable()
ofNullable()方法用来阻止NullPointerExceptions并避免对流进行null检查。
该方法的原型如下:
static <T> Stream<T> ofNullable(T t)
如果传递的元素t非空,则返回由参数元素组成的有序流,否则返回一个空的流。
ofNullable()示例:
package com.morris.java9;
import java.util.stream.Stream;
public class StreamOfNullableDemo {
public static void main(String[] args) {
long count = Stream.ofNullable(100).count();
System.out.println(count);
count = Stream.ofNullable(null).count();
System.out.println(count);
}
}
运行结果如下:
1
0
请注意,使用Stream.ofNullable可以避免在创建流时由于null值而导致的NullPointerException。
如果您尝试使用Stream.of(null)来创建一个包含null的流,将会抛出NullPointerException,因为Stream.of方法不接受 null值作为参数。
Optional类添加了stream()方法
在Java9中,Optional类添加了stream()方法。这个方法允许将一个包含单个元素的Optional对象转换为包含该元素的流。如果Optional对象为空,则生成一个空流。这使得对Optional对象的处理更加灵活,能够更平滑地与其他基于流的操作进行集成。
package com.morris.java9;
import java.util.Optional;
public class OptionalStreamDemo {
public static void main(String[] args) {
// Optional.of,类似Stream.of
long count = Optional.of(100).stream().count();
System.out.println(count);
// Optional.empty,类似Optional.ofNullable/Stream.ofNullable
count = Optional.empty().stream().count();
System.out.println(count);
}
}
运行结果如下:
1
0