Java8中添加了对于Stream API的支持,Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用sql执行的数据库查询。也可以使用Stream API来并行执行操作,Stream API提供了一种高效且易于使用的处理数据的方式。
流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
Stream自己不会存储元素。Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
流的操作过程,创建流,中间操作,终止条件,只有声明终止条件,流才会触发执行。
对应Stream接口
A sequence of elements supporting sequential and parallel aggregate operations. public interface Stream<T> extends BaseStream<T, Stream<T>> {
准备测试数据 准备一个实体类以及相应的集合列表
@Data
public class Dog implements Comparable<Dog> {
private Integer size;
private String name;
private Integer age;
private Integer price;
public Dog(){}
public Dog(String name){
this.name = name;
}
public Dog(Integer size, Integer age){
this.size = size;
this.age = age;
}
public Dog(Integer size, String name, Integer age, Integer price) {
this.size = size;
this.name = name;
this.age = age;
this.price = price;
}
@Override
public int compareTo(Dog o) {
return this.age - o.age;
}
}
List<Dog> dogs = Arrays.asList( new Dog(1, "d1", 2, 5), new Dog(2, "d2", 3, 6), new Dog(3, "d3", 4, 2), new Dog(4, "d4", 1, 3), new Dog(1, "d5", 2, 5), new Dog(2, "d6", 3, 6), new Dog(3, "d7", 4, 2), new Dog(4, "d8", 1, 3));
Stream创建
Stream创建主要有以下方法
1.Collection
集合类流创建
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
2.Arrays
数组流创建
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
3.Stream
创建其他形式流,例如迭代,生成等
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
final Iterator<T> iterator = new Iterator<T>() {
@SuppressWarnings("unchecked")
T t = (T) Streams.NONE;
@Override
public boolean hasNext() {
return true;
}
@Override
public T next() {
return t = (t == Streams.NONE) ? seed : f.apply(t);
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
}
public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
测试如下:
//创建Stream
//1.Collection stream() parallelStream()
List<Dog> list = new ArrayList<>();
Stream<Dog> stream = list.stream();
Stream<Dog> stream2 = list.parallelStream();
//2.Arrays stream()数组流
Dog[] dogarr = new Dog[10];
Stream<Dog> stream3 = Arrays.stream(dogarr);
List<Dog> dog = stream3.collect(Collectors.toList());
System.out.println(dog);
//3.Stream 静态of方法
Stream<String> stream4 = Stream.of("acv", "dsf", "cdv");
//4.无限流
Stream<Integer> stream5 = Stream.iterate(0, (x) -> x + 2);
//stream5.forEach(System.out::println);
//Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
dogs.stream().forEach(System.out::println);
System.out.println("==============");
中间操作
1.筛选切片
按照某种规则进行过滤筛选
/**
* Returns a stream consisting of the elements of this stream that match
* the given predicate.
Stream<T> filter(Predicate<? super T> predicate);
/**
* Returns a stream consisting of the elements of this stream, truncated
* to be no longer than {@code maxSize} in length.
Stream<T> limit(long maxSize);
/**
* Returns a stream consisting of the remaining elements of this stream
* after discarding the first {@code n} elements of the stream.
* If this stream contains fewer than {@code n} elements then an
* empty stream will be returned.
Stream<T> skip(long n);
/**
* Returns a stream consisting of the distinct elements (according to
* {@link Object#equals(Object)}) of this stream.
Stream<T> distinct();
测试如下:
//1.筛选和切片
//filter 根据条件过滤
dogs.stream().filter((x) -> x.getSize() > 1).forEach(System.out::println);
//limit 限制返回个数
dogs.stream().filter((x) -> x.getSize() > 1).limit(2).forEach(System.out::println);
//skip 跳过n个元素 从之后的元素流 若不足n个,则返回空流
dogs.stream().filter((x) -> x.getSize() > 1).skip(2).forEach(System.out::println);
//distinct 去重 根据元素的hashcode和equals方法来去重
dogs.stream().distinct().forEach(System.out::println);
2.映射
将流中每一个元素进行处理并返回
/**
* Returns a stream consisting of the results of applying the given
* function to the elements of this stream.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of a mapped stream produced by applying
* the provided mapping function to each element. Each mapped stream is
* {@link java.util.stream.BaseStream#close() closed} after its contents
* have been placed into this stream. (If a mapped stream is {@code null}
* an empty stream is used, instead.)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
测试:
//2.映射
//map 传入一个函数 应用于每一个元素 返回一个新元素
dogs.stream().map((d) -> d.getSize()).forEach(System.out::println);
//flatMap 传入一个函数 应用于每一个元素产生一个流 返回所有元素产生流的合流
dogs.stream().flatMap((d) -> splitStr(d.getName())).forEach(System.out::println);
3.排序
将流中元素按照某种规则排序
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to natural order. If the elements of this stream are not
* {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown
* when the terminal operation is executed.
Stream<T> sorted();
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the provided {@code Comparator}.
Stream<T> sorted(Comparator<? super T> comparator);
测试
//3.排序
//自然排序 按照Comparable
dogs.stream().sorted().forEach(System.out::println);
//定制排序 Comparator
dogs.stream().sorted((d1, d2) -> Integer.compare(d1.getSize(),
d2.getSize())).forEach(System.out::println);dogs.stream().sorted(Comparator.comparingInt(Dog::getSize)).forEach(System.out::println);
终止操作
1.查找匹配
//1.查找与匹配
//是否匹配所有元素
dogs.stream().allMatch((d) -> d.getSize() == 1);
//是否至少匹配任意一个元素
dogs.stream().anyMatch((d) -> d.getSize() > 1);
//是否没有元素匹配
dogs.stream().noneMatch((d) -> d.getSize() < 100);
//返回任意一个元素
dogs.stream().findAny();
//返回第一个元素
dogs.stream().findFirst();
//总数量
dogs.stream().count();
//最大值
dogs.stream().max(Comparator.comparingInt(Dog::getSize));
//最小值
dogs.stream().min(Comparator.comparingInt(Dog::getSize));
2.归约
/**
* Performs a <a href="package-summary.html#Reduction">reduction</a> on the
* elements of this stream, using the provided identity value and an
* <a href="package-summary.html#Associativity">associative</a>
* accumulation function, and returns the reduced value. This is equivalent
* to:
* <pre>{@code
* T result = identity;
* for (T element : this stream)
* result = accumulator.apply(result, element)
* return result;
* }</pre>
*
* but is not constrained to execute sequentially.
T reduce(T identity, BinaryOperator<T> accumulator);
//2.归约
//reduce 将流中元素反复结合得到新的值
List<Integer> ll = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println(ll.stream().reduce(1, (x, y) -> x * y));
Integer sum = dogs.stream().map((d) -> d.getSize()).reduce(0, Integer::sum);
System.out.println(sum);
3.收集
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream using a
* {@code Collector}. A {@code Collector}
* encapsulates the functions used as arguments to
* {@link #collect(Supplier, BiConsumer, BiConsumer)}, allowing for reuse of
* collection strategies and composition of collect operations such as
* multiple-level grouping or partitioning.
<R, A> R collect(Collector<? super T, A, R> collector);
//3.收集
//将流转换为其他形式
List<String> nl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toList());
List<Dog> dl = dogs.stream().filter((d) -> d.getSize()>1).collect(Collectors.toList());
System.out.println(dl);
Set<String> sl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toSet());
HashSet<String> hsl = dogs.stream().map((d) -> d.getName()).collect(Collectors.toCollection(HashSet::new));
//对应于sql语法
//总数 平均值
System.out.println(dogs.stream().collect(Collectors.counting()));
System.out.println(dogs.stream().collect(Collectors.averagingInt(Dog::getSize)));
//分组
Map<Integer, List<Dog>> m = dogs.stream().collect(Collectors.groupingBy(Dog::getSize));
System.out.println(m);
//多级分组
Map<Integer, Map<Integer, List<Dog>>> mm = dogs.stream().collect(Collectors.groupingBy(Dog::getSize, Collectors.groupingBy(Dog::getAge)));
System.out.println(mm);
//分区
Map<Boolean, List<Dog>> pm = dogs.stream().collect(Collectors.partitioningBy((d) -> d.getSize() > 2));
System.out.println(pm);
//链接
String join = dogs.stream().map((d) -> d.getName()).collect(Collectors.joining());
System.out.println(join);
String join2 = dogs.stream().map((d) -> d.getName()).collect(Collectors.joining(",", "pre", "suf"));
System.out.println(join2);
使用收集类函数,可以将流转换为其他形式,同时进行相应的计算处理,例如分组,分区,连接等。
总之,使用Stream API来操作集合对象还是比较爽的,可以少些很多代码,但是过于使用复杂语法会导致代码阅读难度较大。
参考资料:尚硅谷_Java8新特性