Stream
类Stream是对象和原始数据类型上的流。Stream在几个方面与集合不同:
- 没有存储空间。流不是存储元素的数据结构。相反,它通过一系列计算操作从数据结构,数组,生成器功能或I / O通道等源中传递元素。
- 本质上是功能性的。对流的操作会产生结果,但不会修改其源。例如,对
Stream
从集合中获取的aStream
进行过滤会产生一个不包含过滤后元素的新元素,而不是从源集合中删除元素。 - 懒惰寻求。许多流操作(例如过滤,映射或重复删除)可以延迟执行,从而暴露出优化的机会。例如,“
String
使用三个连续的元音查找第一个”不需要检查所有输入字符串。流操作分为中间(产生Stream
)操作和最终(产生值或副作用)操作。中间操作总是很懒。 - 可能无界。尽管集合的大小是有限的,但流不是必需的。诸如
limit(n)
或 的短路操作findFirst()
可以允许对无限流的计算在有限时间内完成。 - 消耗品。在流的生存期内,流的元素只能访问一次。与一样
Iterator
,必须生成新的流以重新访问源中的相同元素。
stream操作分为中间操作
和终端操作
,合并以形成pipeline
。
-
pipeline
由源(如Collection,数组,生成器函数或I / O通道),零个或多个中间操作以及一个终端操作。 -
中间操作
,执行一个中间操作(如filter)并不会执行实际的过滤操作,而是创建一个新的stream,并将原stream中符合条件的元素放入新创建的stream。 -
终端操作
,会遍历stream并得出结果或者附带结果;在执行终端操作之后,pipeline已经处理完毕,不可以在使用了。
下面对常见的stream操作进行介绍
- filter
- map
- mapToInt
- sorted
- distinct
- forEach,
- sum
- reduce
根据指定模型,计算源内数据,得到一个最终结果
对例子进行解释
Function接口
一个Function<T, R>对象相当于一个函数,其中T是函数参数类型,R是函数返回值类型,等号后面的lambda表达式为函数逻辑。
R apply(T t)相当于函数调用,t为调用函数式传入的参数值。
public class FunctionTest {
public static void main(String[] args) {
Integer num = 5;
System.out.println(functionAdd(num)); // 6
System.out.println(add(num)); // 6
}
public static Integer functionAdd(Integer num){
Function<Integer, Integer> function = x -> x + 1;
return function.apply(num);
}
public static Integer add (Integer num) {
return num + 1;
}
}
Function<V, R> compose()、Function<V, R> andThen()相当于函数组合,源码如下。
/**
* @return a composed function that first applies the {@code before}
* function and then applies this function
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* @return a composed function that first applies this function and then
* applies the {@code after} function
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
根据方法名获取对象方法值
@Data
@AllArgsConstructor
public class Person {
private Double age;
private Double height;
}
@AllArgsConstructor
@Getter
public enum PersonAttribute {
AGE("age", Person::getAge),
HEIGHT("height", Person::getHeight);
private String name;
private Function<Person, Double> getAttribute;
public static PersonAttribute ofName(String name) {
try {
return Arrays.stream(PersonAttribute.values())
.filter(personAttribute -> personAttribute.name.equals(name.trim()))
.findFirst()
.orElseThrow(() -> new Exception("input attribute's name error:" + name));
} catch (Exception exception){
exception.printStackTrace();
}
return null;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person(18D, 160D);
Scanner scanner = new Scanner(System.in);
PersonAttribute personAttribute = PersonAttribute.ofName(scanner.nextLine());
System.out.println(personAttribute.getGetAttribute().apply(person));
}
}
::
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps