1.流操作
分为两大类:中间操作和终端操作,可以连接起来的流操作称为中间操作,关闭流的操作称为终端操作。
2.中间操作和终端操作
例如filter等中间操作会返回另一个流,除非流水线上触发一个终端操作,否则中间操作不会执行任何处理,它们很懒。这是因为中间操作一般都可以合并起来,在终端操作时一次性全部处理。
流的使用一般包括三个步骤:生成流,中间操作,终端操作
常用的中间操作:filter,map,limit,sorted,distinct
常用的终端操作:forEach,count,collect
3.流的特性
3.1 流不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值),流一个来自数据源的元素队列,它更像一个高级版本的 Iterator。原始的Iterator只能显式地一个一个遍历元素并对其执行某些操作,Stream可以过滤元素进行操作,Stream会隐式地 在内部进行遍历,做出相应的数据转换,但是只能单向的遍历一次
3.2 使用stream流对集合元素或者数组元素操作时,源数据并不改变
3.3 流只能遍历一次,用完之后就不存在了,只能重新创建流才能使用
3.4 并行化:for循环性能 > parallelStream(并行流)性能 > Stream(普通流)性能 , parallelStream是一个并行执行的流,可以提高多线 程任务的速度
parallelStream流的forEach是并行的,所以打印出的是乱序的,用forEachOrdered又变成并序的了
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(System.out::println);
numbers.parallelStream().forEachOrdered(System.out::println);
3.5 惰性:流的惰性与流的中间操作有关,流的中间操作将会为最终操作创建另一个流,但不会执行实际的处理,这有助于提升性 能
3.6 短路行为:对中间操作进行短路操作,一旦满足条件流将会终止操作,分为有状态中间操作和无状态中间操作,无状态中间操作 性能更高
有状态中间操作:distinct(),sort(),limit()
无状态中间操作:filter(),map()
4.流常用操作
4.1获取流
4.1.1 所有Collection集合都可以通过stream默认方法获取流
4.1.2 将数组转成流
double[] numbers = {1.1, 2.2,3.3,4.4,5.5};
Arrays.stream(numbers).forEach(System.out::println);
输出:
1.1
2.2
3.3
4.4
5.5
4.1.3 由值生成流
IntStream number = IntStream.of(1,2,3,4);
number.forEach(System.out::println);
Stream<String> name = Stream.of("ZS","WHY","LMY","LF","SY","ZQM","HXL");
name.forEach(System.out::println);
输出:
1
2
3
4
ZS
WHY
LMY
LF
SY
ZQM
HXL
4.1.4从文件中获取流
Stream<String> context = null ;
try {
context = Files.lines(Paths.get("D:\\abc.txt"));
} catch (IOException e) {
e.printStackTrace();
}
context.forEach(System.out::println);
输出
dsadsadsadasdasdsffghghjhhgfhdfsdsdsdgfg
4.1.5 从函数中生成流
Stream中有两个静态方法生成流:Stream.iterate,Stream.generate,这两个方法可以生成无限流,所以一定要加limit限制大小
Stream.iterate
输入:表示从1开始,x每次都加2
Stream.iterate(1, x->x+2).
limit(10).forEach(System.out::println);
输出:
1
3
5
7
9
11
13
15
17
19
再如:斐波那契数列,第三个数等于前两个数的和
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
.limit(20)
.map(t -> t[0])
.forEach(System.out::println);
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
Stream.generate
输入:
IntSupplier fib = new IntSupplier() {
private int previous = 0;
private int current = 1;
@Override
public int getAsInt() {
int oldPrevious = this.previous;
int nextValue = this.previous + this.current;
this.previous = this.current;
this.current = nextValue;
return oldPrevious;
}
};
IntStream.generate(fib).limit(10).forEach(System.out::println);
输出:斐波那契数列
0
1
1
2
3
5
8
13
21
34
4.1.6 Map生成流
输入
Map<String, Object> map = new HashMap<>();
map.put("name","WHY");
map.put("AGE",26);
map.put("SEX","MAN");
Stream<Map.Entry<String, Object>> stream = map.entrySet().stream();
stream.forEach(System.out::println);
输出:
SEX=MAN
name=WHY
AGE=26
4.2 forEach遍历
List<Integer> num = Arrays.asList(1,2,3,4,5,6);
num.stream().forEach(System.out::println);
输出:
1
2
3
4
5
6
4.3 过滤
4.3.1 filter 返回满足条件的数
List<Integer> num = Arrays.asList(1,2,3,4,5,6);
num.stream().filter(i -> i>2).filter(i ->i<5).forEach(System.out::println);
输出:
3
4
4.3.2 distinct 返回不重复的数据
List<String> names = Arrays.asList("why","hehe","hehe","why","HAHA");
names.stream().distinct().forEach(System.out::println);
输出:
why
hehe
HAHA
4.3.3 limit 限制返回元素个数
输入:
List<String> names = Arrays.asList("why","hehe","hehe","why","HAHA");
names.stream().distinct().limit(2).forEach(System.out::println);
输出:
why
hehe
4.3.4 skip 跳过前n个元素
输入:
List<String> names = Arrays.asList("why","hehe","hehe","why","HAHA");
names.stream().skip(2).forEach(System.out::println);
输出:
hehe
why
HAHA
4.4 Map映射
4.4.1 map方法作用于每个元素,并且返回一个新的元素,map可以改变Stream的类型,例如下面例子把int变成了String
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().filter(i->i>=1).filter(j ->j<4).map(a->"第"+a+"个").forEach(System.out::println);
输出:
第1个
第2个
第3个
4.4.2 flatMap
flatMap方法可以把各个数组映射的流合为一个流
String str= "I love the world";
Stream<String> strStream = Stream.of(str);
strStream.flatMap(line->Arrays.stream(line.split(" "))).forEach(System.out::println);
输出:数组中每个元素的值
I
love
the
world
如果用map的话
String str= "I love the world";
Stream<String> strStream = Stream.of(str);
strStream.map(line->Arrays.stream(line.split(" "))).forEach(System.out::println);
输出:一个流的数组
java.util.stream.ReferencePipeline$Head@1cf53f9
4.5 sorted 排序
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
num.stream().sorted().forEach(System.out::println);
输出:
1
2
3
4
4
6
7
4.6 规约
4.6.1 reduce将流中的元素结合得到一个值
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
Integer sum = num.stream().reduce(Integer::sum).get();
System.out.println(sum);
Integer max = num.stream().reduce(Integer::max).get();
System.out.println(max);
Integer min = num.stream().reduce(Integer::min).get();
System.out.println(min);
输出:
27
7
1
4.6.2 max和min,参数是Comparator
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
Integer max = num.stream().max(comparing(Integer::intValue)).get();
System.out.println(max);
Integer min = num.stream().min(comparing(Integer::intValue)).get();
System.out.println(min);
输出:
7
1
4.6.3 Collectors 可将流转换成集合和聚合元素
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
List<Integer> newNum = num.stream().filter(i -> i>2).collect(Collectors.toList());
System.out.println(newNum);
输出:
[4, 6, 7, 3, 4]
输入:合并字符串
List<String> strings = Arrays.asList("I", "LOVE", "THE", "WORLD","hehe");
String mergedString = strings.stream().filter(string -> !string.equals("hehe")).
collect(Collectors.joining(" "));
System.out.println(mergedString);
输出:
I LOVE THE WORLD
4.7 判断
4.7.1 anyMatch 表示是否存在满足要求的元素,有的话返回true
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
boolean result = num.stream().anyMatch(i->i==1);
System.out.println(result);
返回:
true
4.7.2 allMatch 表示所有元素都满足条件才返回true
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
boolean result = num.stream().allMatch(i->i==1);
System.out.println(result);
输出:
false
4.7.3 noneMatch 表示是否一个元素都不满足条件,与anyMatch相反
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
boolean result = num.stream().noneMatch(i->i==1);
System.out.println(result);
输出:
false
4.7.4 findFirst 返回第一个元素
输入:
List<Integer> num = Arrays.asList(4,2,6,1,7,3,4);
Integer result = num.stream().findFirst().get();
System.out.println(result);
输出:
4
4.8 数值流
Stream<Integer>有装箱拆箱的操作,而IntStream,DoubleStream和LongStream分别表示流中的元素为int,double,long,可以避免装箱拆箱
4.8.1
输入:
public class Number {
String name;
int num;
public Number(String name, int num) {
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
List<Number> list = Arrays.asList(new Number("why",60),new Number("hehe",70));
IntStream intStream = list.stream().mapToInt(a -> a.getNum());
int sum = intStream.sum();
System.out.println(sum);
IntStream intStream2 = list.stream().mapToInt(a -> a.getNum());
int max = intStream2.max().getAsInt();
System.out.println(max);
IntStream intStream3 = list.stream().mapToInt(a -> a.getNum());
int min = intStream3.min().getAsInt();
System.out.println(min);
IntStream intStream4 = list.stream().mapToInt(a -> a.getNum());
double ave = intStream4.average().getAsDouble();
System.out.println(ave);
输出:
130
70
60
65.0
4.8.2 range,rangeClosed
生成范围内的数,第一个参数接受起始值,第二个参数接受结束值,range不包含结束值,rangeClosed包含结束值
输入:
IntStream.range(1, 100).filter(i->i>95).forEach(System.out::println);
输出:
96
97
98
99