什么是 Stream?
- Stream是一个来自数据源的元素队列并支持聚合操作。元素是特定类型的对象,形成一个队列。
Java中的Stream并不会存储元素,而是按需计算。数据源流的来源可以是集合,数组,I/O channel, 产生器generator
等。聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。
这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。 - 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。
Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
Stream的操作符大体上分为两种
- 中间操作符
map(mapToInt,mapToLong,mapToDouble) 转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","grape")
.map(e->e.length()) //转成单词的长度 int
.forEach(e->System.out.println(e));
}
}

package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","grape")
.mapToInt(e -> e.length()) //转成int
.forEach(e -> System.out.println(e));
}
}
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","grape")
.mapToLong(e -> e.length()) //转成long ,本质上是int 但是存在类型自动转换
.forEach(e -> System.out.println(e));
}
}
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("apple","banana","orange","grape")
.mapToDouble(e -> e.length()) //转成Double ,自动类型转换成Double
.forEach(e -> System.out.println(e));
}
}
flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) 拍平操作比如把 int[]{2,3,4} 拍平 变成 2,3,4 也就是从原来的一个数据变成了3个数据,这里默认提供了拍平成int,long,double的操作符。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("1-2-3-4","5-6-7-8-9")
.flatMap(e->Stream.of(e.split("-")))
.forEach(e->System.out.println(e));
}
}

limit 限流操作,比如数据流中有10个 我只要出前3个就可以使用。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,4,5,6)
.limit(3) //限制三个
.forEach(e->System.out.println(e)); //将输出 前三个 1,2,3
}
}

distint 去重操作,对重复元素去重,底层使用了equals方法。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(1,1,2,5,0,0,1,2,3,1)
.distinct() //去重
.forEach(e->System.out.println(e));
}
}

filter 过滤操作,把不想要的数据过滤。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(1,1,2,5,0,0,1,2,3,1)
.filter(e->e>=2) //过滤小于2的
.forEach(e->System.out.println(e));
}
}

peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
User w = new User("a",1);
User x = new User("b",2);
User y = new User("c",3);
Stream.of(w,x,y)
.peek(e->{e.setAge(e.getAge()+5);}) //age+5
.forEach(e->System.out.println(e.toString()));
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}

skip 跳过操作,跳过某些元素。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(1,2,3,4,5,6)
.skip(4) //跳过前四个
.forEach(e->System.out.println(e)); //输出的结果应该只有5,6
}
}

sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(2,1,3,6,4,9,6,8,0)
.sorted()
.forEach(e->System.out.println(e));
}
}
- 终止操作符
collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors。
package com.company;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of("apple", "banana", "orange", "grape")
.collect(Collectors.toSet()) //set 容器
.forEach(e -> System.out.println(e));
}
}

count 统计操作,统计最终的数据个数。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
long count = Stream.of("apple", "banana", "orange", "grape")
.count();
System.out.println(count);
}
}

findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。
package com.company;
import java.util.Optional;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "grape")
.findFirst();
stringOptional.ifPresent(e->System.out.println(e));
}
}

package com.company;
import java.util.Optional;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "grape")
.parallel()
.findAny(); //在并行流下每次返回的结果可能一样也可能不一样
stringOptional.ifPresent(e->System.out.println(e));
}
}
noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
boolean result = Stream.of("aa","bb","cc","aa")
.noneMatch(e->e.equals("aa"));
System.out.println(result);
}
}

min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值。
package com.company;
import java.util.Optional;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-7)
.min((e1,e2)->e1.compareTo(e2));
integerOptional.ifPresent(e->System.out.println(e));
}
}

package com.company;
import java.util.Optional;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-7)
.max((e1,e2)->e1.compareTo(e2));
integerOptional.ifPresent(e->System.out.println(e));
}
}
reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
int sum = Stream.of(0,8,4,5,6,-7)
.reduce(0,(e1,e2)->e1+e2);
System.out.println(sum);
}
}

forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Stream.of(99,2,36,5,48,9,8,-1)
.parallel()
.forEachOrdered(e->{
System.out.println(Thread.currentThread().getName()+": "+e);});
}
}

toArray 数组操作,将数据流的元素转换成数组。
package com.company;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Object[] objects=Stream.of(99,2,36,5,4,9,8,-7)
.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
}
}

基本操作都比较简单。
版权声明:本文为qq_27790251原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。