- Stream是Java8中处理集合的关键抽象概念,可以指定希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream来并行执行操作
- Stream和Collection集合的区别:
Collection是一种静态的内存数据结构,Stream是有关计算的。 - 需要注意的三点
1⃣️Stream自己不会存储数据(所以建立在集合的基础上)
2⃣️Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream
3⃣️Stream操作是延迟执行的,他们会等到需要结果的时候再执行
操作Stream的三个步骤
- 创建Stream:通过数据源(集合、数组)获取一个流
- 中间操作:中间操作链,对数据源的数据进行处理
- 终止操作:一旦执行终止操作,就执行中间操作链,并产生结果,之后不会再被使用(延迟执行)
创建Stream
- 方式一:通过集合
//通过集合创建stream List接口中的默认方法
@Test
public void test1(){
List integers = Arrays.asList(1, 2, 4, 5, 7, 8, 9, 9);
//default Stream stream():返回一个顺序流
Stream stream = integers.stream();
//default Stream parallelStream():返回一个并行流
Stream parallelStream = integers.parallelStream();
}
- 方式二:通过Arrays
通过Arrays中的静态方法,能够处理对应基本类型的数组生成相应的流(IntStream,LongStream,DoubleStream),也可以生成带泛型的流
//通过数组Arrays中的静态方法
@Test
public void test2(){
int[] arrs = new int[]{1,2,4,5,6,6,7,7};
IntStream stream = Arrays.stream(arrs);
String[] names = new String[]{"ssy","cf"};
Stream stringStream = Arrays.stream(names);
}
- 方式三:通过Stream的of()
@Test
public void test3(){
Stream stream = Stream.of(1,2,4,5,5,8);
}
- 方式四:通过Stream创建无限流
@Test
public void test4(){
//public static Stream iterate(T seed, java.util.function.UnaryOperator f)
Stream.iterate(0,t->t+2).limit(20).forEach(System.out::println);
//public static Stream generate(java.util.function.Supplier s)
Stream.generate(Math::random).limit(20).forEach(System.out::println);
}
Stream的中间操作
多个中间操作可以链接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”
1、筛选与切片
-
filter(Predicate p)
接受Lambda,从流中排除某些元素 -
distinct()
筛选,通过流生成元素的hashcode和equals去除重复元素 -
limit(long maxSize)
截断流,使元素不超过给定的数量 -
skip(long n)
跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流
@Test
public void test5(){
List names = Arrays.asList("Tom", "Ssy", "Cf", "Sherry", "Juddy");
Stream stream = names.stream();
stream.filter(name -> name.length()<=3).forEach(System.out::println);
System.out.println("*************");
//终止操作后不能再操作该stream,需要重新生成
names.stream().limit(3).forEach(System.out::println);
System.out.println("**************");
names.stream().skip(2).forEach(System.out::println);
System.out.println("****************");
List names1 = new ArrayList<>(names);//因为asList的结果不能add了
names1.add("Yu");
names1.add("Yu");
names1.add("Yu");
names1.add("Yu");
System.out.println(names1.toString());
names1.stream().distinct().forEach(System.out::println);
}
2、映射
-
map(Function f)
接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射为一个新的元素 -
flatMap(Function f)
接收一个函数作为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流 - 两者之间的关系类似于下述关系
@Test
public void test6(){
List list=new ArrayList(Arrays.asList(1,2,3,4));
List list1 = Arrays.asList(5,6,7,8);
list.add(list1);
System.out.println(list);
List list2=new ArrayList(Arrays.asList(1,2,3,4));
list2.addAll(list1);
System.out.println(list2);
}
- 例子
@Test
public void test7(){
//map
List strings = Arrays.asList("aa", "bb", "cc");
strings.stream().map(String::toUpperCase).forEach(System.out::println);
//flatMap
strings.stream().map(StreamTest::fromStringToStream).forEach(System.out::println);
strings.stream().flatMap(StreamTest::fromStringToStream).forEach(System.out::println);
}
public static Stream fromStringToStream(String str){
char[] strs = str.toCharArray();
ArrayList arrs = new ArrayList<>();
for(char c:strs){
arrs.add(c);
}
return arrs.stream();
}
3、排序
- 自然排序与定制排序
@Test
public void test8(){
//sorted()
List integers = Arrays.asList(34, 64, 23, 6, 53, 77);
integers.stream().sorted().forEach(System.out::println);
//sorted(Comparator com)
List employees = new ArrayList<>();
employees.stream().sorted((e1,e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);
}
Stream的终止操作
终止操作会从流的流水线生成结果,其结果可以是任何不是流的指,例如List、Integer,甚至是void。流进行终止操作后,不能再次使用
1、匹配与查找
-
allMatch(Predicate p)
检查是否匹配所有元素 -
anyMatch(Predicate p)
检查是否至少匹配一个元素 -
noneMatch(Predicate p)
检查是否没有元素匹配 -
findFirst()
返回第一个元素 -
findAny()
返回当前流中的任意元素 -
count()
返回流中元素的总个数 -
max(Comparator)
返回流中的最大值 -
min(Comparator)
返回流中的最小值 -
forEach(Consumer c)
内部迭代
2、规约
-
reduce(T identity, BinaryOperator b)
可以将流中的元素反复结合起来,得到一个值,返回T
@Test
public void test9(){
//计算1-10自然数的和
Integer reduce = Stream.iterate(1, e -> e + 1).limit(10).reduce(0, Integer::sum);
System.out.println(reduce);
}
-
reduce(BinaryOperator b)
可以将流中的元素反复结合起来,得到一个值,返回 Optional(在optional相关类中再讲)
3、收集
-
collect(Collector c)
将流转换为其他形式,接受一个collector接口的实现,用于给Stream中元素做汇总的方法 - Collectors实用类,方便地创建常见收集器实例
@Test
public void test10(){
List integers = Arrays.asList(34, 64, 23, 6, 53, 77);
List collect = integers.stream().collect(Collectors.toList());
collect.forEach(System.out::println);
}