Stream流
stream流,是在java8中,由lambda表达式所带来的一种新的函数是编程模式,可以用来解决一些已有的集合类型的弊端。
1.stream流与传统集合的便利方式的区别
传统遍历方式
1 public static void main(String[] args) { 2 //遍历输出名字中含有七的并且名字长度为3的人 3 List<String> list = List.of("乔七七","韩七岁","零零七","鲁班七号","上官婉儿"); 4 5 List<String> newList = new ArrayList<>(); 6 //遍历list挑选出名字中带有七的 7 for (String s : list) { 8 if (s.contains("七")){ 9 newList.add(s); 10 } 11 } 12 13 //遍历出名字长度为3的 14 for (String s : newList) { 15 if (s.length()==3){ 16 System.out.println(s); 17 } 18 } 19 }
stream方式
1 public static void main(String[] args) { 2 List<String> list = List.of("乔七七","韩七岁","零零七","鲁班七号","上官婉儿"); 3 //筛选带七的且名字长度为3的人 4 list.stream().filter(s -> s.contains("七")) 5 .filter(s -> s.length()==3) 6 .forEach(System.out::println); 7 }
emmm
,是不是很简单明了。
2.stream流思想原理
当对集合中的元素需要进行一系列的操作,我们可已按照需要的规则来进行处理这些集合中的数据。
在这个图中显示了过滤,映射,跳过,计数等多个环节,将这些步骤都放在一起进行一个流水线一样的操作,整个过程在一个管道中完成,将数据又由原始状态转变为需要的状态。
filter
、map
、skip
都是在对函数模型进行操作,集合元素并没有真正被处理。只有当终结方法count
执行的时候,整个数据才会按照指定要求执行操作。
3.stream流中常用的方法
stream流中方法可分为两类,一种为终结方法,另外一种为非终结方法。
终结方法:返回值类型不再是
Stream
接口自身类型的方法。非终结方法:返回值仍然是stream接口的方法,支持链式调用。
过滤:filter
filter
方法将一个流转换为另外一个子集流。
Stream<T> filter(Predicate<? super T> predicate);
该接口接收一个Predicate
函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。
1 public static void main(String[] args) { 2 Stream<String> stream = Stream.of("鲁班七号", "老夫子", "公孙离", "南宫", "甄姬"); 3 stream.filter(s -> s.length() == 2).forEach(System.out::println); 4 5 }
截取:limit
limit
方法可以对流进行截取,只取用前n个。
Stream<T> limit(long maxSize);
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作
1 public class StreamLimit { 2 public static void main(String[] args) { 3 Stream<String> stream = Stream.of("鲁班七号", "老夫子", "公孙离", "南宫", "甄姬"); 4 //limit截取前几个元素 5 stream.limit(3).forEach(System.out::println); 6 } 7 }
跳过:skip
skip
方法可以跳过前几个元素,从而获取之后的元素作为一个新的流。
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
1 public class StreamSkip { 2 public static void main(String[] args) { 3 //skip跳过几个元素 4 Stream<String> stream = Stream.of("鲁班七号", "老夫子", "公孙离", "南宫", "甄姬"); 5 stream.skip(2).forEach(System.out::println); 6 } 7 }
映射:map
map
方法可以将需要的元素映射到另外一个集合中。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要一个Function
函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
1 public class StreamMap { 2 public static void main(String[] args){ 3 Stream<String> oldStream = Stream.of("1.2", "1.3", "3.5", "12.5", "65.8"); 4 Stream<Double> newStream = oldStream.map(Double::parseDouble); 5 newStream.forEach(System.out::println); 6 } 7 }
联合:concat
如果有两个流,希望合并成为一个流,那么可以使用Stream
接口的静态方法concat
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
基本使用:
1 public static void main(String[] args) { 2 //concat,合并流 3 Stream<String> wurenxiaofendui = Stream.of("孙悟空", "猪八戒", "沙和尚", "小白龙", "唐僧"); 4 Stream<String> yaojingwurenzu = Stream.of("紫霞","嫦娥","小侍女","四公主","女儿国国王"); 5 Stream<String> stringStream = Stream.concat(wurenxiaofendui, yaojingwurenzu); 6 stringStream.forEach(System.out::println); 7 }
计数:count
count方法用来统计个数
long count();
使用:
1 public class ListDemo { 2 public static void main(String[] args) { 3 4 List<String> list = List.of("乔七七","韩七岁","零零七","鲁班七号","上官婉儿"); 5 //筛选带七的且名字长度为3的人,统计个数 6 long count = list.stream(). 7 filter(s -> s.contains("七")). 8 filter(s -> s.length() == 3).count(); 9 System.out.println(count); 10 } 11 }
遍历处理:forEach
forEach
,但是与for循环中的“for-each”昵称不同,该方法并不保证元素的逐一消费动作在流中是被有序执行的。
void forEach(Consumer<? super T> action);
该方法接收一个Consumer
接口函数,会将每一个流元素交给该函数进行处理。
1 import java.util.stream.Stream; 2 3 public class StreamForEach { 4 public static void main(String[] args) { 5 6 Stream<String> stream = Stream.of("孙悟空", "猪八戒", "沙和尚", "小白龙", "唐僧"); 7 stream.forEach(System.out::println); 8 } 9 }