Stream使用

1、什么是Stream

stream是支持数据处理操作的源生成的元素序列,添加了很多操作,如查找、过滤、分组、排序等,它不是一种数据结构,简言之,Stream提供了一套高效且易于使用的数据处理方式。
特点:

  • 不存储元素;
  • 不改变源对象,返回一个持有结果的新的Stream;
  • 当有终端操作时才会执行。

2、Stream执行操作

2.1 创建Stream

集合创建

java8在Collecton接口中,提供了两个获取流的方法,也就是说凡是实现Collection接口的实现类,都可以通过这两个方法获取到Stream。

default Stream stream(); //返回一个顺序流。
default Stream parallelStream(); //返回一个并行流。
List<User> users = new ArrayList<>();
users.add(new User("Jack",9));
users.add(new User("Kreas",10));
users.add(new User("Marry",13));
users.add(new User("Timi",14));

Stream<User> stream = users.stream();
Stream<User> userStream = users.parallelStream();

数组创建

Java8 中的 Arrays 的静态方法 stream() 可以获取数组流,并且该方法生成的流是数值流而不是 Stream。补充一点使用数值流可以避免计算过程中拆箱装箱,提高性能。

int[] intArray = {1,2,3};
IntStream stream = Arrays.stream(intArray);

值创建

可以使用静态方法 Stream.of(), 通过显示值 创建一个流。它可以接收任意数量的参数。
public static Stream of(T… values) : 返回一个流。

 Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);

通过文件生成

Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());

通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行.

通过函数生成

iterator

Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5);

iterate方法接受两个参数,第一个为初始化值,第二个为进行的函数操作,因为iterator生成的流为无限流,通过limit方法对流进行了截断,只生成5个偶数。
generator

Stream<Double> stream = Stream.generate(Math::random).limit(5);

generate方法接受一个参数,方法参数类型为Supplier ,由它为流提供值。generate生成的流也是无限流,因此通过limit对流进行了截断。

2.2 Stream中间操作

Stream中间操作主要是对流进行操作,返回一个新的流,交给下一个操作使用。当中间操作有多个时,就会形成中间操作链,需要注意一点,如果只有中间操作,那这些操作并不会执行,只有在执行终端操作时,操作才会执行,这种方式叫做延迟加载或者惰性求值。

distinct()

去重操作

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",10);
User user3 = new User("Marry",13);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user1);
users.stream().distinct().forEach(u -> System.out.println(u.getName()));
// Jack Kreas Marry Timi

filter

通过使用filter方法进行条件筛选,filter的方法参数为一个条件(过滤保留函数返回值为 true 的元素)

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",10);
User user3 = new User("Marry",13);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.stream().filter(u -> u.getAge() > 12)
                .forEach(u -> System.out.println(u.getName()));
// Marry Timi

limit

通过limit方法指定返回流的个数,limit的参数值必须 >=0,否则将会抛出异常。通常与排序配合使用。

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",10);
User user3 = new User("Marry",13);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.stream().limit(2)
        .forEach(u -> System.out.println(u.getName()));
// Jack Kreas

sorted

指定比较规则进行排序。

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",17);
User user3 = new User("Marry",12);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.stream().sorted(Comparator.comparing(User::getAge).reversed())
                    .forEach(u -> System.out.println(u.getName()));
// Kreas Timi Marry Jack

skip

跳过指定个数元素

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",17);
User user3 = new User("Marry",12);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.stream().skip(2)
             .forEach(u -> System.out.println(u.getName()));
// Marry Timi

map

接收一个Function函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。也就是转换操作,map还有三个应用于具体类型方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型。这三个方法可以免除自动装箱/拆箱的额外消耗。

List<User> users = new ArrayList<>();
User user1 = new User("Jack", 9);
User user2 = new User("Kreas",17);
User user3 = new User("Marry",12);
User user4 = new User("Timi", 14);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.stream().map(user -> "欢迎 "+ user.getName())
        .forEach(System.out :: println);
/**
欢迎 Jack
欢迎 Kreas
欢迎 Marry
欢迎 Timi
*/

flatMap

接收一个Function函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流。flatMap也有三个应用于具体类型的方法,分别是:flatMapToInt、flatMapToLong、flatMapToDouble,其作用于map的三个衍生方法相同。

List<String> wordList = Arrays.asList("Java 8", "Lambdas", "In", "Action");

List<String> strList = wordList.stream()
        .map(w -> w.split(" "))
        .flatMap(Arrays::stream)
        .distinct()
        .collect(Collectors.toList());
// [Java, 8, Lambdas, In, Action]

map(w -> w.split(" ")) 的返回值为 Stream<String[]>,想获取 Stream,可以通过flatMap方法完成 Stream ->Stream 的转换。

2.3 终端操作

foreach

内部迭代

users.stream().forEach(user -> System.out.println(user.getName()));

collect

收集、将流转换为其他形式,比如转换成List、Set、Map。collect方法是用Collector作为参数,Collector接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例。例举一些常用的

List<User> users = Lists.newArrayList();
users.add(new User(15, "A", ImmutableList.of("1元", "5元")));
users.add(new User(25, "B", ImmutableList.of("10元", "50元")));
users.add(new User(21, "C", ImmutableList.of("100元")));
 //收集名称到List
List<String> nameList = users.stream().map(User::getName).collect(Collectors.toList());
 //收集名称到List
Set<String> nameSet = users.stream().map(User::getName).collect(Collectors.toSet());
 //收集到map,名字作为key,user对象作为value
Map<String, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getName, Function.identity(), (k1, k2) -> k2));

allMatch

匹配所有元素

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
if (integerList.stream().allMatch(i -> i > 3)) {
    System.out.println("所有元素值都大于3");
} else {
    System.out.println("并非所有元素值都大于3");
}

anyMatch

匹配其中一个

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
if (integerList.stream().anyMatch(i -> i > 3)) {
    System.out.println("存在值大于3的元素");
} else {
    System.out.println("不存在值大于3的元素");
}

noneMatch

全部不匹配

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
if (integerList.stream().noneMatch(i -> i > 3)) {
    System.out.println("值都小于3的元素");
} else {
    System.out.println("值不都小于3的元素");
}

其他终端操作

  • Optional findFirst(); 返回当前流中的第一个元素。
  • Optional findAny(); 返回当前流中的任意元素。
  • long count(); 返回流中元素总数。
  • Optional max(Comparator<? super T> comparator); 返回流中最大值。
  • Optional min(Comparator<? super T> comparator); 返回流中最小值。
  • T reduce(T identity, BinaryOperator accumulator); 可以将流中元素反复结合起来,得到一个值。 返回 T。这是一个归约操作。

参考博客:
https://blog.csdn.net/QiuHaoqian/article/details/120942134
https://blog.csdn.net/weixin_43966635/article/details/109113579

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值