java8 stream流操作
概念:
Steam 是Java8 提出的一个新概念,不是输入输出的 Stream 流,而是一种用函数式编程方式在集合类上进行复杂操作的工具。简而言之,是以内部迭代的方式处理集合数据的操作,内部迭代可以将更多的控制权交给集合类。Stream 和 Iterator 的功能类似,只是 Iterator 是以外部迭代的形式处理集合数据的操作。
在Java8以前,对集合的操作需要写出处理的过程,如在集合中筛选出满足条件的数据,需要一 一遍历集合中的每个元素,再把每个元素逐一判断是否满足条件,最后将满足条件的元素保存返回。而Stream 对集合筛选的操作提供了一种更为便捷的操作,只需将实现函数接口的筛选条件作为参数传递进来,Stream会自行操作并将合适的元素同样以stream 的方式返回,最后进行接收即可。
中间操作
流中间操作在应用到流上,返回一个新的流。下面列出了常用的流中间操作:
- map:通过一个 Function 把一个元素类型为 T 的流转换成元素类型为 R 的流。
- flatMap:通过一个 Function 把一个元素类型为 T 的流中的每个元素转换成一个元素类型为 R 的流,再把这些转换之后的流合并。
- filter:过滤流中的元素,只保留满足由 Predicate 所指定的条件的元素。
- distinct:使用 equals 方法来删除流中的重复元素。
- limit:截断流使其最多只包含指定数量的元素。
- skip:返回一个新的流,并跳过原始流中的前 N 个元素。
- sorted:对流进行排序。
- peek:返回的流与原始流相同。当原始流中的元素被消费时,会首先调用 peek 方法中指定的 Consumer 实现对元素进行处理。
- dropWhile:从原始流起始位置开始删除满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。
- takeWhile:从原始流起始位置开始保留满足指定 Predicate 的元素,直到遇到第一个不满足 Predicate 的元素。
终结操作
终结操作产生最终的结果。
- forEach 和 forEachOrdered 对流中的每个元素执行由 Consumer 给定的实现。在使用 forEach 时,并没有确定的处理元素的顺序;forEachOrdered 则按照流的相遇顺序来处理元素,如果流有确定的相遇顺序的话。
- reduce进行递归计算
- collect生成新的数据结构
Map
将一种类型的值映射为另一种类型的值,可以将 Stream 中的每个值都映射为一个新的值,最终转换为一个新的 Stream 流。
public class MapStreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("aa","bb","cc");
//这里str -> str.toUpperCase()即为Function接口中apply方法的实现,所以其作用就是转为大写。
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
//这个同上,是lambda的简写
list.stream().map(String::toUpperCase).forEach(System.out::println);
}
Filter
遍历并筛选出满足条件的元素形成一个新的 Stream 流。
public class FilterStreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("java", "zhi", "hu", "javascript");
//筛选已j开头的字符串的个数
long count = list.stream().filter(p -> p.startsWith("j")).count();
System.out.println(count);
}
flatMap
可用 Stream 替换值,并将多个 Stream 流合并成一个 Stream 流。
public class FlatMapStreamTest {
public static void main(String[] args) {
List<Integer> list = Stream.of(Arrays.asList(1, 2, 3, 4, 5, 6), Arrays.asList(8, 9, 10, 11, 12)).flatMap(test -> test.stream()).collect(Collectors.toList());
}
reduce(终止操作)
从 Stream 的一组值中生成另一个值。可以理解为递归。
public class ReduceStreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
//这里0是初始值,第一次执行规约应该是0+1,其中1是第一个值 x是累计结果值,y是当前值
Integer sum = list.stream().reduce(0, (x,y) -> x + y);
System.out.println("sum:"+sum);
}
他就是一个不断 累计运算 的过程
stream.collect()方法
<R, A> R collect(Collector<? super T, A, R> collector);
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
第1个方法,我们主要是使用 Collectors来进行各种 reduction 操作
- Collectors.toSet() : 转换成set集合。
- Collectors.toMap(x -> x, x -> x + 1) : 转换成map。
- Collectors.minBy(Integer::compare) : 求最小值,相对应的当然也有maxBy。
- Collectors.joining("-") : 拼接字符串。
- 。。。(一系列方法)
public class CollectTest {
public static void main(String[] args) {
//将数组转为集合List
String[] arr ={"aa","ccc","sss"};
System.out.println(Arrays.stream(arr).collect(toList()));
//将list中的数据分组 并统计数量
List<Person> list = Arrays.asList(person1,person2,person3);
Map<Integer, Long> personGroups = list.stream().collect(Collectors.groupingBy(Person::getAge,counting()));
}
第2个方法
- Supplier 生产者, 返回最终结果
- BiConsumer<R, ? super T> accumulator 累加器
- 第一个参数是要返回的集合, 第二个参数是遍历过程中的每个元素,将流中每个被遍历的元素添加到集合中
- BiConsumer<R, R> combiner 合并器, 在有并行流的时候才会有用, 一个流时代码不会走到这里
- 将第二步遍历得到的所有流形成的list都添加到最终的list中
public class CollectTest {
public static void main(String[] args) {
Stream<String> stream = Stream.of("hello", "world", "helloworld");
List<String> list = stream.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
}
Optional
具有以下两个特点:
- 判断是否为null
- 简化if else代码
public final class Optional<T> {
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
private Optional() {
this.value = null;
//创建一个空的 Optional 实例
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
private Optional(T value) {
this.value = Objects.requireNonNull(value);
//创建一个 Optional 实例,当 t为null时抛出异常
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
//创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
//获取optional实例中的对象,当optional 容器为空时报错
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
return value;
//判断optional是否为空,如果空则返回false,否则返回true
public boolean isPresent() {
return value != null;
//如果optional不为空,则将optional中的对象传给Comsumer函数
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
//如果optional不为空,则执行断言函数p,如果p的结果为true,则返回原本的optional,否则返回空的optional
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
return predicate.test(value) ? this : empty();
//如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
//同上,在optional不为空的情况下,将对象t映射成另外一个optional。
//区别:map会自动将u放到optional中,而flatMap则需要手动给u创建一个optional
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
// //如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值
public T orElse(T other) {
return value != null ? value : other;
//如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
//如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
if (!(obj instanceof Optional)) {
return false;
Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
@Override
public int hashCode() {
return Objects.hashCode(value);
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
demo
public class OptionalTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.debit = new Debit();
p1.debit.card = new Card();
p1.debit.card.bank = new Bank();
p1.debit.card.bank.name = "ICBC";
Person p2 = new Person();
p2.debit = new Debit();
p2.debit.card = new Card();
Person p3 = new Person();
p3.debit = new Debit();
p3.debit.card = new Card();
p3.debit.card.bank = new Bank();
Person p4 = new Person();
p4.debit = new Debit();
p4.debit.card = new Card();
p4.debit.card.bank = new Bank();
p4.debit.card.bank.name = "ZSBC";
Person p5 = new Person();
//普通方法取值 VS Optional
List<Person> list = Arrays.asList(p1,p2,p3,p4, p5);
list.stream().map(OptionalExample::getDebitBankName_1).forEach(System.out::println);
System.out.println("");
list.stream().map(OptionalExample::getDebitBankName_2).forEach(System.out::println);
System.out.println("");
public static String getDebitBankName_1(Person person) {
if (person.getDebit()!=null) {
Debit debit = person.getDebit();
if (debit!=null) {
Card card = debit.getCard();
if (card != null) {
Bank bank = card.getBank();
if (bank != null) {
return bank.getName();
return null;
}else {
return null;
public static String getDebitBankName_2(Person person) {
return Optional.ofNullable(person.getDebit())