StreamAPI
Java8API中添加了新的抽象称为流Stream,把真正的函数式编程风格引入到Java中,可以让你以一种声明的方式处理数据,Stream使用一种类似SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象,StreamAPI极大简化了集合框架的处理,这种风格将需要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如:筛选、排序、聚合。
Stream流有一些新特性:
Stream流不是一种数据类型,不保存数据,他只是在原数据集上定义了一组操作这些操作是惰性的,即每当访问到这个流中的一个元素时,才会在此元素上执行这一系列的操作Stream流不保存数据,所以一个Stream流只能使用一次元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果:
中间操作:返回结果都是Stream,所以中间操作可以叠加最终操作:返回我们最终需要的数据,只能有一个最终操作
使用Stream流,可以清楚地知道我们要对一个数据集做何操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以更加专注于业务逻辑。默认情况下,从有序集合、生成器、迭代器产生的流或者通过调用Stream.sorted产生的流都是有序流,有序流在并行处理时会在处理完成后恢复原顺序。无限流的存在侧面说明了流是惰性的,即每当用到一个元素时,才会在这个元素上执行这一系列操作。
使用Stream流的基本操作:
创建Stream转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以进行多次转换)对Stream进行聚合操作,获得想要的结果
流的创建
通过集合创建
Java8中Collection接口被扩展,提供了两个获取流的方法:
default Stream stream();返回一个顺序流default Stream parallelStream();返回一个并行流
通过数组创建
Java8中的Arrays的静态方法stream()可以获取数组流
public staticStream staram(T[] array);返回一个流public static IntStream stream(int[] array);返回一个整型的数据流public static LongStream stream(long[] array);返回一个长整形的数据流public static DoubleStream stream(double[] array);返回一个浮点型数据流
通过Stream创建
1、可以调用Stream类静态方法of(),通过显示值创建一个流,它可以接收任务数量的参数。
public static Stream of(T …values);返回一个顺序流
2、静态方法concat(),将两个流连接起来
public static Stream concat(Stream<? extends T> a, Stream<? extends T> b);
创建无限流
可以使用Stream中的静态方法Stream.iterate()和Stream.generate(),创建一个无限流
public static Stream iterate(final T seed,final UnaryOperatorf);返回一个无限流public static Stream generate(Supplier s);返回一个无限流
中间操作
返回值方法名说明
Streamfilter(Predicate p)筛选,接收Lambda,从流中排除某些元素Streamdistinct()筛选,通过流所生成元素的equals()去除重复元素Streamlimit(long maxSize)截断,使流中元素不超过指定maxSizeStreamskip(long n)切片,跳过元素,返回一个扔掉了n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补Streampeek(Consumer action)消费,接收Lambda,对流中每一个数据执行Lambda体操作Streamsorted()排序,产生一个新流,其中按自然顺序排序Streamsorted(Comparator com)排序,产生一个新流,其中按给定比较器顺序排序Streammap(Function f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素StreamflatMap(Function f)映射,接收一个函数作为参数,将流中的每一个值都替换为另一个流,然后把所有流连接成一个流DoubleStreammapToDouble(ToDoubleFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的DoubleStreamIntStreammapToInt(ToIntFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的IntStreamLongStreammapToLong(ToLongFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的LongStream
中间操作:筛选和切片
ArrayList
<Employee> list
= new ArrayList<>();
list
.add(new Employee(1001,"张三",3000));
list
.add(new Employee(1002,"李四",5500));
list
.add(new Employee(1003,"王五",8000));
list
.add(new Employee(1004,"赵六",6000));
list
.add(new Employee(1004,"赵六",6000));
list
.add(new Employee(1004,"赵六",6000));
list
.stream()
.filter((x
)->x
.getSalary()>5000)
.limit(4)
.skip(1)
.distinct()
.forEach(System
.out
::println
);
中间操作:消费
List
<String> list2
= Arrays
.asList("a","bb","c","d");
list2
.stream()
.peek(System
.out
::println
)
.collect(Collectors
.toList());
中间操作:排序
List
<String> list1
= Arrays
.asList("dd","b","aaa","cccc");
list1
.stream()
.sorted()
.forEach(System
.out
::println
);
System
.out
.println("-----------------------------------------");
list1
.stream()
.sorted((a
,b
)-> {
if (a
.length() > b
.length()){
return 1;
}else {
return -1;
}
})
.forEach(System
.out
::println
);
中间操作:映射
String
[] strs
= {"java","lambda","stream","map","flatmap"};
Arrays
.stream(strs
)
.map((str
)->str
.split(""))
.forEach(System
.out
::println
);
Arrays
.stream(strs
)
.map((str
)->str
.split(""))
.flatMap(Arrays
::stream
)
.forEach(System
.out
::println
);
终结操作
终结操作是会从流的流水线生成结果,其结果可以是任何不是流的值,如List、Integer、void也可以。流进行了终止操作后,就不能再次使用。
返回值方法名说明
booleanallMatch(Predicate p)接收一个Predicate函数,当流中每个元素都符合该断言时,才会返回true,否则返回falsebooleannoneMatch(Predicate p)接收一个Predicate函数,当流中每一个元素都不符合该断言时才返回true,否则返回falsebooleananyMatch(Predicate p)接收一个Predicate函数,当流中有一个元素满足该断言则返回true,否则返回falseOptionalfindFirst()返回流中的第一个元素OptionalfindAny()返回流中的任意一个元素longcount()返回流中元素的总个数Optionalmax(Comparator c)返回流中元素的最大值Optionalmin(Comparator c)返回流中元素的最小值voidforEach(Consumer c)遍历操作,对此流的每个元素执行操作Treduce(T iden,BinaryOperator b)规约操作,使用提供的身份值和 associative累积函数对此流的元素执行reduction,并返回减小的值。Ureduce(BinaryOperator b)规约操作,使用提供的身份,积累和组合功能,对此流的元素执行reductionRcollect(Collector c)收集操作,收集一个Collector实例,将流中元素收集成另一个数据结构
终结操作:查找
ArrayList
<Employee> list
= new ArrayList<>();
list
.add(new Employee(1001,"张三",3000));
list
.add(new Employee(1002,"李四",5500));
list
.add(new Employee(1003,"王五",8000));
list
.add(new Employee(1004,"赵六",6000));
boolean b1
= list
.stream()
.allMatch(e
-> e
.getSalary()>3000);
System
.out
.println("员工工资是否都大于3000:"+b1
);
boolean b2
= list
.stream()
.anyMatch(e
-> e
.getSalary()>7000);
System
.out
.println("员工工资是否有大于7000的:"+b2
);
boolean b3
= list
.stream()
.noneMatch(e
-> e
.getSalary()>10000);
System
.out
.println("员工工资是否都不大于一万:"+b3
);
Optional
<Employee> op
= list
.stream()
.sorted(Comparator
.comparingDouble(Employee
::getSalary
))
.findFirst();
System
.out
.println("工资最低的员工:"+op
.get());
Optional
<Employee> op1
= list
.parallelStream()
.filter(e
->e
.getSalary()>5000)
.findAny();
System
.out
.println("工资大于5000的任意一个员工:"+op1
.get());
终结操作:匹配
long count
= list
.stream()
.count();
System
.out
.println("员工总数为:"+count
);
Optional
<Employee> op3
= list
.stream()
.max(Comparator
.comparingDouble(Employee
::getSalary
));
System
.out
.println("工资最高的员工:"+op3
.get());
Optional
<Double> op4
= list
.stream()
.map(Employee
::getSalary
)
.min(Double
::compare
);
System
.out
.println("最低工资为:"+op4
.get());