stream流

创建操作

数组

通过调用Arrays.stream(T[])取得数组的stream

1
2
3
4
5
6
7
8
9
String[] strArr = new String[]{"a1", "a2", "a3"};
Stream<String> stream = Arrays.stream(strArr);

stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

单列集合

单列集合直接通过集合中所属的方法调用,取得集合的stream

1
2
3
4
5
6
7
8
9
10
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3");

Stream<String> stream = list.stream();
stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

双列集合

双列集合无法像单列集合一样直接通过函数调用得到stream流,所以只能通过entrySet()keySet()取得单列集合,然后再取得stream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Map<String, String> map = new HashMap<>();
map.put("key1", "val1");
map.put("key2", "val2");
map.put("key3", "val3");

Set<String> keySet = map.keySet();
Stream<String> stream = keySet.stream();
stream.forEach(new Consumer<String>() {
@Override
public void accept(String key) {
String val = map.get(key);
System.out.println("key=" + key + " - val=" + val);
}
});

Set<Map.Entry<String, String>> entrySet = map.entrySet();
Stream<Map.Entry<String, String>> stream1 = entrySet.stream();
stream1.forEach(new Consumer<Map.Entry<String, String>>() {
@Override
public void accept(Map.Entry<String, String> stringEntry) {
System.out.println("key=" + stringEntry.getKey() + " - val=" + stringEntry.getValue());
}
});

散元素

散元素又与以上三种方式不同,通过调用Stream类下的静态方法of(T...)来完成散元素的数据流

1
2
3
4
5
6
7
8
9
10
11
String v1 = "val1";
String v2 = "val2";
String v3 = "val3";

Stream<String> stream = Stream.of(v1, v2, v3);
stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

中间操作

filter(Predicate<T>)筛选元素

Predicate<T>中重写test(T)方法,test(T)方法返回true时,元素保留,否则元素被过滤

1
2
3
4
5
6
7
8
9
10
11
stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("a");
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

map(Function<T, R>)转换流中元素的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3", "b1", "b2");

Stream<String> stream = list.stream();
stream.map(new Function<String, Integer>() {
@Override
public Integer apply(String str) {
// 截取元素中的整数
String number = str.substring(str.length() - 1);
return Integer.parseInt(number);
}
}).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});

flatMap(Function<T, R>)把流中的数据映射为新的流

通俗来讲,对stream流中的子元素做一些操作,得到一个新的stream流,新的stream流将称为原来的流中的一部分,所以当把集合中的五个元素拆分为String数组,并且把数组的streamreturn后,那么现在的流中其实是拆分后的十个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3", "b1", "b2");

Stream<String> stream = list.stream();
List<String> collect = stream.flatMap(new Function<String, Stream<String>>() {
@Override
public Stream<String> apply(String str) {
// 把字符串拆分成数组,并且把数组转换成stream流
// 这些“子流”将会重新装入“主流”中
return Arrays.stream(str.split(""));
}
})
// 把流中的数据收集到集合中
.collect(Collectors.toList());

// 将会输出 [a, 1, a, 2, a, 3, b, 1, b, 2]
System.out.println(collect);

sorted(Comparator<T>)排序

说实话这个升序和降序返回-1还是1我每次都忘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3", "b1", "b2");
Collections.shuffle(list);

Stream<String> stream = list.stream();
stream.sorted(new Comparator<String>() {
@Override
public int compare(String s, String t) {
// 取元素第一位在ASCII中的编码
int s1 = s.charAt(0);
int t1 = t.charAt(0);
// 取元素第二位,并转换成int类型
int s2 = Integer.parseInt(s.split("")[1]);
int t2 = Integer.parseInt(t.split("")[1]);

if (s1 != t1)
// 根据第一位升序
return s1 - t1;
else
// 第一位相同,根据第二位升序
return s2 - t2;
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

limit(int)截取元素

1
2
3
4
5
6
7
8
stream.limit(3)
.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
// 将只会输出前三个元素
System.out.println(s);
}
});

skip(int)跳过元素

1
2
3
4
5
6
7
8
stream.skip(1)
.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
// 将会跳过第一个元素
System.out.println(s);
}
});

distinct()元素去重

1
2
3
4
5
6
7
stream.distinct()
.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

peek(Consumer<T>)用于观察元素的中间方法

其实和forEach(Consumer<T>)差不多,但是作为中间方法会返回原来的stream流,主要用于在开发过程中看一下元素是不是符合原来的预期

1
2
3
4
5
6
stream.peek(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
}).count();

Stream.concat(Stream<T>, Stream<R>)合并两个stream

1
2
3
4
5
6
7
8
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3", "b1", "b2");

List<String> list2 = new ArrayList<>();
Collections.addAll(list2, "s1", "s2");

Stream<String> concat = Stream.concat(list.stream(), list2.stream());
concat.forEach(System.out::println);

终结操作

forEach(Consumer<T>)遍历

1
2
3
4
5
6
stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});

count()统计流长度

1
long count = stream.count();

toArray()收集流中的数据,放在数组中

1
Object[] array = stream.toArray();

collect()将流中的数据收集到集合中

将流中的数据收集到List集合中

1
stream.collect(Collectors.toList());

将流中的数据收集到Set集合中

1
stream.collect(Collectors.toSet());

将流中的数据收集到Map集合中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
List<String> list = new ArrayList<>();
Collections.addAll(list, "a1", "a2", "a3");

Stream<String> stream = list.stream();

Map<Integer, String> collect = stream.collect(Collectors.toMap(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
// 返回key
return Integer.parseInt(s.split("")[1]);
}
}, new Function<String, String>() {
@Override
public String apply(String s) {
// 返回val
return s;
}
}));