Stream的简单使用
文章目录
一、简述
Java8的新特性,stream(流)是一个来自数据源的元素队列并支持聚合操作,就是将多个操作流程串联成一个管道,通过这个管道对其中的数据进行筛选,排序,聚合等操作,最终输出我们需要的过程,简化了操作流程。stream
特点:1.不是数据结构,不会保存数据。
2.不会修改原来的数据,将操作后的数据保存到另外的一个对象中。
3.延迟执行,在中间处理过程中只是进行记录,不会立即执行,只有等到执行终止操作的时候才会进行计算。
二、分类
中间操作就像水管的一部分,终端就像水龙头,增加水管长度不会消耗水,只有打开了水龙头才会消耗水
操作分类:中间状态(无状态、有状态),终结操作(短路、非短路)
无状态:指元素的处理不受之前元素的影响。(如map或者filter会从输入流中获取每一个元素,并且在输出流中得到一个结果,这些操作没有内部状态)
有状态:指该操作只有拿到所有元素之后才能继续下去。(1.像reduce、sum、max这些操作都需要内部状态来累计计算结果 2.像sort、distinct、limit、skip他们在接受一个流,再生成一个流,但是在排序和去重项需要知道先前的历史,这些操作也是有状态操作的。)
流是否有状态的判断标准,就是看是否需要知道先前的数据历史,前后数据是否有依赖关系来判断
短路:指遇到某些符合条件的元素就可以得到最终结果。
非短路:指必须处理完所有元素才能得到最终结果。(如A||B,只要A为true,则无需判断B的结果)
对于有无状态可能会想到编程里的也有无状态(编程里有状态就是有数据存储功能,线程不安全,无状态就是一次操作,不能保存数据。线程安全),spring中的有无状态等。
三、用法
1.生成stream流的方式
1. 1.Collection体系集合
使用默认方式stream()生成流,default Stream stream()
List<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
list.add("feg");
Stream<String> lists = list.stream(); //获取一个顺序流
Stream<String> listp = list.parallelStream();// 获取一个并行流
System.out.println(lists.collect(Collectors.joining(",")));
System.out.println(listp.collect(Collectors.joining(",")));
Set<String> set = new HashSet<>();
Stream<String> sets = set.stream();
看了这个案例,就想知道什么是顺序流和并行流吧,安排
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Fork-Join框架:是Java7提供的一个用于执行任务的框架,就是在必要的情况下,将一个大任务,进行拆分(Fork)成若干个小任务(拆分到不能再拆分),再将一个个的小任务运算的结果进行Join汇总(采用“工作窃取”模式) 。
提问:FORK/JOIN 框架与传统线程池的区别?
传统线程池在执行任务的时候,如果一个线程在执行过程中由于某些原因无法继续运行,那么该线程就处于等待状态,而在fork/join框架中,如果在该线程中发生阻塞,后面的任务会被其他空闲的线程来进行执行,减少了等待时间,提高了性能。
//拆分任务
public class ParallelFlow extends RecursiveTask<Long> {
private long start;
private long end;
private static final long THRESHOLD = 10000;//阈值0
public ParallelFlow(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end - start;
//如果不到临界值就执行加操作
if(length <= THRESHOLD){
long sum = 0;
for (long i = start; i < end ; i++) {
sum += i;
}
return sum;
}else{
long middle = (start+end)/2;
ParallelFlow left = new ParallelFlow(start,end);
left.fork();//拆分子任务,同时压入线程队列
ParallelFlow right = new ParallelFlow(middle+1,end);
right.fork();
return left.join()+right.join();
}
}
}
//测试类
public class StreamTest {
public static void main(String[] args) {
new StreamTest().fun1();//fork/join框架耗时
fun2();//for循环耗时
stramfun1();//串行耗时
stramfun2();//并行耗时
}
//Fork/Join框架
public void fun1(){
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ParallelFlow task = new ParallelFlow(0,10000L);
Long sum = pool.invoke(task);
System.out.println(sum);
Instant end = Instant.now();
System.out.println("Fork/Join框架耗时为:"+Duration.between(start,end).toMillis());
}
//普通for循环
public static void fun2(){
Instant start = Instant.now();
long sum = 0L;
for(long i = 0 ; i < 10000L ; i++){
sum += i;
}
System.out.println(sum);
Instant end = Instant.now();
System.out.println("for循环耗时为:"+Duration.between(start,end).toMillis());
}
//串行流
public static void stramfun1(){
Instant start = Instant.now();
LongStream.rangeClosed(0,10000L).parallel().reduce(0,Long::sum);
Instant end = Instant.now();
System.out.println("stream串行流耗时时间:"+ Duration.between(start,end).toMillis());
}
//并行流
public static void stramfun2(){
Instant start = Instant.now();
LongStream.rangeClosed(0,10000L).sequential().reduce(0,Long::sum);
Instant end = Instant.now();
System.out.println("stream并行流耗时:"+Duration.between(start,end).toMillis());
}
}
//结果
49995000
Fork/Join框架耗时为:0
49995000
for循环耗时为:0
stream串行流耗时时间:80
stream并行流耗时:0
1. 2.Map体系集合
把map转成set集合,间接的生成流
Map<Integer,String> map = new HashMap<>();
map.put(1,"第一");
map.put(2,"第二");
map.put(3,"第三");
Stream<Integer> keystream = map.keySet().stream();
Stream<String> valuestream = map.values().stream();
Stream<Map.Entry<Integer,String>> entryStream = map.entrySet().stream();
1. 3.数组
String[] str = {"one","two","three"};
Stream<String> s1 = Stream.of(str);
System.out.println(s1.collect(Collectors.joining(",")));
2.中间操作
1. 1.有状态
去重distinct
List<String> list = Arrays.asList("ma","zhi","chu","zhi","shuo","ma");
list = list.stream().distinct().collect(Collectors.toList());
System.out.println(list);
//结果:[ma, zhi, chu, shuo]
跳过skip
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
list.stream().skip(4).forEach(System.out::print);
//结果:56789
截断limit
List<String> words = Arrays.asList("one","two","three","four","five");
List<String> limitword = words.stream().limit(3).collect(Collectors.toList());
System.out.println(limitword);
//结果:[one, two, three]
排序sorted
List<Integer> nums = Arrays.asList(1,3,5,6,8,2);
List<Integer> sortedNum = nums.stream().sorted().collect(Collectors.toList());
System.out.println("自然排序:"+sortedNum);
List<Integer> descNum = nums.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
System.out.println("降序排序:"+descNum);
//结果:自然排序:[1, 2, 3, 5, 6, 8]
// 降序排序:[8, 6, 5, 3, 2, 1]
1. 2.无状态
过滤filter
List<Integer> nums = Arrays.asList(1,3,5,6,8,2);
List<Integer> filterNum = nums.stream().filter(n -> n>5).collect(Collectors.toList());
System.out.println(filterNum);
//结果:[6, 8]
映射map
List<String> list1 = Arrays.asList("one","two","three");
List<String> list2 = list1.stream().map(n -> n.toUpperCase()).collect(Collectors.toList());
System.out.println("转换成大写:"+list2);
List<Integer> list3 = list2.stream().map(n -> n.hashCode()).collect(Collectors.toList());
System.out.println("转换成hash值:"+list3);
//结果:转换成大写:[ONE, TWO, THREE]
// 转换成hash值:[78406, 83500, 79801726]
扁平化flatMap
List<Integer> num1 = Arrays.asList(1,2,3);
List<Integer> num2 = Arrays.asList(4,5,6);
List<Integer> num3 = Arrays.asList(7,8,9);
List<List<Integer>> lists = Arrays.asList(num1,num2,num3);
Stream<Integer> outputStream = lists.stream().flatMap(n -> n.stream());
List<Integer> flatMapResult = outputStream.sorted().collect(Collectors.toList());
System.out.println(flatMapResult);
//结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]
遍历peek
String[] arr = new String[]{"a","b","c","d"};
Arrays.stream(arr).peek(System.out::print).count();
//结果:abcd
3.终端操作
1. 1.短路
匹配所有allMatch
List<Integer> ins = Arrays.asList(1,2,3,4,5);
boolean a = ins.stream().allMatch(n -> n>3);
boolean b = ins.stream().allMatch(n -> n>6);
System.out.println("a:"+a+" b:"+b);
//结果:a:false b:false
//allMatch表示stream中所有元素都满足条件为true,否则false
任意匹配anyMatch
List<Integer> ins = Arrays.asList(1,2,3,4,5);
boolean a = ins.stream().allMatch(n -> n>3);
boolean b = ins.stream().allMatch(n -> n>6);
System.out.println("a:"+a+" b:"+b);
//结果:a:true b:false
//allMatch表示stream中所有元素有一个满足条件为true,否则false
不匹配noneMatch
List<Integer> ins = Arrays.asList(1,2,3,4,5);
boolean a = ins.stream().noneMatch(n -> n>3);
boolean b = ins.stream().noneMatch(n -> n>6);
System.out.println("a:"+a+" b:"+b);
//结果:a:false b:true
//allMatch表示stream中所有元素都不满足条件为true,否则false
查找首个findFirst
List<Integer> integers = Arrays.asList(2, 2, 3);
Optional<Integer> first = integers.stream().findFirst();
System.out.println(first);
System.out.println(first.isPresent());// 判断是否不等于null,isPresent()相当于!=null的判断
//结果:Optional[2]
// true
//如果流为空,返回一个空的Optional
1. 2.非短路
遍历forEach
Stream.of(1,2,3,4,5,6).forEach(System.out::print);
//结果:123456
归约reduce
String reduceStr1 = Stream.of("ma", "zhi", "chu").reduce("", String::concat);
//结果:mazhichu
最大值max
List<Integer> num = Arrays.asList(1, 2, 3, 4, 5, 6);
Integer maxNum = num.stream().max(Integer::compareTo).get();
System.out.println(maxNum);
//结果:6
最小值min
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
Integer minNum = nums.stream().min(Integer::compareTo).get();
System.out.println(maxNum);
//结果:1
聚合collect
List<Integer> skipNum = IntStream.range(1,100).skip(90).boxed().collect(Collectors.toList());
System.out.println(skipNum);
//结果:[91, 92, 93, 94, 95, 96, 97, 98, 99]
计数count
List<Integer> ls = Arrays.asList(1,2,3,4,5);
long count = ls.stream().count();
System.out.println(count);
//结果:5