1.介绍
-
Stream API把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以较大提高Java程序员的生产力,让程序员写出干净、效率、整洁的代码
-
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查询、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式
-
Stream API vs 集合框架
Stream API关注的是多个数据的计算(排序、查找、过滤、映射、遍历),是面向CPU的;集合关注的是数据的存储,是面向内存的
2.使用说明
- Stream自己不会存储元素
- Stream不会改变源对象。相反,它们会返回一个持有结果的新Stream
- Stream操作是延迟执行的。这意味着它们会等到需要结果的时候才执行。即一旦执行终止操作,就执行中间操作链,并产生结果
- Stream一旦执行了终止操作,就不能调用其它中间操作或终止操作了
3.Stream的执行流程
(1) Stream的实例化
如:
public void test1(){
//1.创建Stream实例
//方式1:通过集合创建
List<User> users = UserData.getUsers();
Stream<User> stream = users.stream();
//方式2:通过数组创建
int[] array = new int[]{1,4,5,7,9};
IntStream stream1 = Arrays.stream(array);
//方式3:通过stream.of创建
Stream<String> aa = Stream.of("aa", "bb", "cc", "dd");
}
(2) Stream一系列的中间操作
注:只有执行了终止操作,中间操作才会执行
a.筛选与切片
方法 | 描述 |
---|---|
filter(Predicate predicate) | 过滤出指定条件的元素集合 |
limit(long maxSize) | 获取前maxSize条元素 |
skip(long n) | 跳过前n条元素 |
distinct() | 去重,需要重写equals()和hashcode()方法 |
代码演示:
@Test
public void test2(){
//练习1:filter(Predicate predicate)过滤
//获取工资大于20000的用户
users.stream().filter(user -> user.getSalary() > 20000).forEach(System.out::println);
}
@Test
public void test3(){
//练习2:limit(long maxSize)
//获取前5条用户
users.stream().limit(5).forEach(System.out::println);
}
@Test
public void test4(){
//练习3:skip(long n)
//跳过前五条用户
users.stream().skip(5).forEach(System.out::println);
}
@Test
public void test5(){
//练习4:distinct()
//去重,需要重写equals()和hashcode()方法
users.stream().distinct().forEach(System.out::println);
}
b.映射
代码演示:
@Test
public void test6(){
//映射
//1.转换大小写
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
strings.stream().map(String :: toUpperCase).forEach(System.out::println);
//2.筛选出用户姓名长度大于4的用户的姓名
users.stream().filter(user -> user.getName().length() > 4).map(User :: getName).forEach(System.out::println);
}
c.排序
代码演示:
//排序
//1.自然排序
List<String> strings = Arrays.asList("dfd", "gg", "dd", "ss", "mm");
strings.stream().sorted().forEach(System.out::println);
System.out.println("***************************");
//2.定制排序
users.stream().sorted((o1, o2) -> (int) (o1.getSalary() - o2.getSalary())).forEach(System.out::println);
System.out.println("***************************");
//3.字符串从大到小
strings.stream().sorted((o1,o2) -> o2.compareTo(o1)).forEach(System.out::println);
d.匹配与查找
方法 | 描述 |
---|---|
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
findFirst() | 返回第一个元素 |
count | 返回流中的元素总个数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Comsumer c) | 内部迭代 |
代码演示:
@Test
public void test8(){
//匹配与查找
//1.allMatch(Predicate p)
System.out.println(users.stream().allMatch(user -> user.getSalary() > 10000));
//2.anyMatch(Predicate p)
System.out.println(users.stream().anyMatch(user -> user.getSalary() > 40000));
//3.findFirst()
System.out.println(users.stream().findFirst());
//4.count()
System.out.println(users.stream().count());
//5.max(Comparator c)
System.out.println(users.stream().max((o1,o2) -> Double.compare(o1.getSalary(),o2.getSalary())));
//6.min(Comparator c)
System.out.println(users.stream().map(User::getSalary).min((o1, o2) -> Double.compare(o1, o2)));
//7.forEach()
users.stream().filter(user -> user.getSalary() > 30000).forEach(System.out::println);
//注意,jdk8之后,List也有forEach方法
users.forEach(user -> System.out.println(user.getName()));
}
e.规约
方法 | 描述 |
---|---|
reduce(T identity,BinaryOperator) | 可以将流中元素反复结合起来,得到一个值,返回T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值,返回Optional |
代码演示:
@Test
public void test9(){
//规约
//1.计算1-9元素之和
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println(integers.stream().reduce(0, Integer::sum));
//2.计算所有用户工资之和
System.out.println(users.stream().map(User::getSalary).reduce(Double::sum));
}
f.收集
方法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式,接收一个Collector接口的实现,返回一个List或Set |
代码演示:
@Test
public void test10(){
//收集
//1.返回工资大于20000的用户,返回到一个新的List中
List<User> collect = users.stream().filter(user -> user.getSalary() > 20000).collect(Collectors.toList());
collect.forEach(System.out::println);
//2.按照用户的工资排序,返回到一个新的List中
users.stream().sorted(Comparator.comparingDouble(User::getSalary)).collect(Collectors.toList()).forEach(System.out::println);
}
}