虽然说这是1.8的“新特性”,但我相信仍有部分同僚还没能掌握,当然这并不是什么多牛逼的技能,但其可以帮助我们能看懂同事写的代码,避免扯皮。
这篇文章将会介绍stream流的使用,相信看完会有不小的收获,废话不多说,步入正题
案例一
1.1
-
创建一个集合,存储多个字符串元素
-
把集合中所有以"张"开头的元素存储到一个新的集合
-
把"张"开头的集合中的长度为3的元素存储到一个新的集合
-
遍历上一步得到的集合
1.2原始代码示例
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1,"张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤");
//遍历list1把以张开头的元素添加到list2中。
ArrayList<String> list2 = new ArrayList<>();
for (String s : list1) {
if(s.startsWith("张")){
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,再添加到list3中。
ArrayList<String> list3 = new ArrayList<>();
for (String s : list2) {
if(s.length() == 3){
list3.add(s);
}
}
for (String s : list3) {
System.out.println(s);
}
1.3流的实现
ArrayList<String> list =
new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
// //过滤出姓张的同学;
// list.stream().filter(s -> s.startsWith("张"));
// //过滤出长度为3的同学
// list.stream().filter(s -> s.length() == 3);
// //终止操作
// list.stream().forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3)
.forEach(s -> System.out.println(s));
1.3.1流的三种方法
stream流类似于流水线,在过程中可以多次对其操作
1.获取stream流
可以理解为创建一条流水线,准备进行工作。
2.中间方法
理解为对流水线进行一步步操作,所以说每个中间方法可以对上一个中间方法的结果进行操作。
3.终结操作
每个流水线只有一个终结操作,可以理解流水线上任务完成进行打包。
1.3.2生成流的三种方式
-
1 Collection体系集合(List Set)
-
使用默认方法stream()生成流
-
-
2 Map体系集合
-
把Map转成Set集合(keySet,entrySet),间接的生成流
-
keySet().stream() 或者 entrySet().stream()
-
-
3 数组
-
通过Arrays中的静态方法stream生成流 Arrays.stream(arr)
-
-
4 同种数据类型的多个数据
-
通过Stream接口的静态方法of(T... values)生成流 , 原理还是数组变流
-
1.3.3代码演示
//1 Collection类都用stream方法
ArrayList<Object> list = new ArrayList<>();
Stream<Object> stream = list.stream();
//2 Map
HashMap<Object, Object> map = new HashMap<>();
//2.1先获取key的集合
Set<Object> keys = map.keySet();
//再使用集合的stream方法
Stream<Object> MapKeysStream = keys.stream();
//2.2获取集合中键值对的集合,再使用集合的stream方法
Set<Map.Entry<Object, Object>> entries = map.entrySet();
Stream<Map.Entry<Object, Object>> entryStream = entries.stream();
//3 数组
int[] ints = {1, 3, 4, 5, 6, 7, 8};
IntStream arrStream = Arrays.stream(ints);
//4 可变参数
Stream<String> stringStream = Stream.of("李白", "杜甫", "白居易", "王勃");
1.4Stream流的中间操作
1.4.1概念
-
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
1.4.2常见方法
方法名 | 说明 |
---|---|
Stream<T> filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream<T> limit(long maxSize) | 返回流中最前面 指定参数个数的数据组成的流 |
Stream<T> skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
static <T> Stream<T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream<T> distinct() | 返回 去掉流数据中 重复的元素后剩余数据组成的流 |
1.4.3filter代码
流的操作不影响原集合的数据
ArrayList<String> al = new ArrayList<String>();
Collections.addAll(al, "周润发", "成龙", "小明", "刘德华", "吴京", "周星驰", "李连杰");
Stream<String> stringStream = al.stream().filter(s -> s.length() == 3);
//每一个数据都会进入到test方法,并且返回长度为3的元素
al.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length()==3;
}
});
1.4.4 limit skip代码
ArrayList<String> al = new ArrayList<String>();
Collections.addAll(al, "周润发", "成龙", "小明", "刘德华", "吴京", "周星驰", "李连杰");
al.stream().limit(3).skip(1).forEach(s -> System.out.println(s)a);
1.4.5 concat 和distinct
ArrayList<String> al = new ArrayList<String>();
Collections.addAll(al, "周润发", "成龙", "小明", "刘德华", "吴京", "周星驰", "李连杰"); ArrayList<String> al1 = new ArrayList<String>();
Collections.addAll(al1, "林心如", "张曼玉", "林青霞", "柳岩", "林志玲", "小明", "王祖贤");
Stream<String> stream = al1.stream();
Stream<String> stream1 = al.stream();
Stream.concat(stream,stream1).forEach(s -> System.out.println(s));
//去重后合并流
Stream.concat(stream,stream1).distinct().forEach(s -> System.out.println(s));
1.5 Stream流终结操作方法
1.5.1概念
-
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
1.5.2常见方法
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行操作 |
long count() | 返回此流中的元素数 |
1.5.3代码
ArrayList<String> al = new ArrayList<String>();
Collections.addAll(al, "周润发", "成龙", "小明", "刘德华", "吴京", "周星驰", "李连杰");
al.stream().forEach(s -> System.out.println(s));
//获取流中的数量
long count = al.stream().count();
1.5.4 collect收集操作
-
collect方法 获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.
-
Collectors提供了具体的收集方式
-
收集到List 、收集到Set、收集到Map
-
方法名 | 说明 |
---|---|
public static <T> Collector toList() | 把元素收集到List集合中 |
public static <T> Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
//添加重复数据,方便演示toset
for (int i = 0; i < 4; i++) {
list.add(10);
}
Stream<Integer> stream = list.stream();
//收集元素变为set集合
Set<Integer> set = stream
.filter(integer -> integer % 2 == 0)
.collect(Collectors.toSet());
//收集元素变为list集合
List<Integer> list1 = stream
.filter(integer -> integer > 5)
.collect(Collectors.toList());
//收集元素变为数组
Object[] objects = stream
.filter(integer -> integer % 2 == 0)
.toArray();
//变为指定数组
Integer[] integers = stream
.filter(integer -> integer > 5)
.toArray(Integer[]::new);
Integer[] integers1 = stream.filter(integer -> integer > 5)
.toArray(value -> new Integer[value]);
1.5.5收集到map中
ArrayList<String> al = new ArrayList<String>(List
.of("001,周润发", "002,成龙", "003,小明", "004,刘德华", "005,吴京"));
//把集合的数据 存到map里 序号作为key 人名作为值 {"001":"周润发","002":"成龙"}
//lambda写法
Map<String, String> map = al.stream()
.collect(Collectors.toMap(s -> s.split(",")[0],
s -> s.split(",")[1]));
al.stream()
.collect(Collectors.toMap(
new Function<String, String>() {
@Override
public String apply(String s) {
//返回值作为key 一般会通过处理s得到
return s.split(",")[0];
}
}, new Function<String, String>() {
@Override
public String apply(String s) {
//返回值value 一般会通过处理s得到
return s.split(",")[1];
}
}));
以上就是stream流的基本操作了,但愿看后能够有所帮助