首页 > 编程语言 >java Stream流练习

java Stream流练习

时间:2022-11-01 11:44:06浏览次数:63  
标签:info java Stream stream 练习 22 User new user

1.遍历/匹配(foreach/find/match)

Stream也是支持类似集合的遍历和匹配元素的,只是Stream中的元素是以Optional类型存在的。Stream的遍历、匹配非常简单。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 7, 8, 9, 0, 100);
// find使用,查找第一个元素
Optional<Integer> first = list.stream().findFirst();
log.info(first.get().toString());

// match使用,判断是否存在某个值
boolean b1 = list.stream().anyMatch(value -> value >= 100);
boolean b2 = list.stream().anyMatch(value -> value > 10);
log.info(String.valueOf(b1));
log.info(String.valueOf(b2));

// foreach使用,遍历输出元素
list.stream().filter(value -> value > 4).forEach(System.out::print);
System.out.println();
list.forEach(System.out::print);

2.筛选(filter)

筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

// 数字筛选
List<Integer> list = Arrays.asList(1, 3, 4, 5, 6, 7, 8, 9, 10, 20);

ArrayList<Integer> arrayList1 = new ArrayList<>();
list.stream().filter(value -> value > 4).forEach(value -> arrayList1.add(value));
log.info(arrayList1.toString());

ArrayList<Integer> arrayList2 = new ArrayList<>();
list.stream().filter(value -> value <= 4).forEach(arrayList2::add);
log.info(arrayList2.toString());

// 对象筛选
List<User> userList1 = Arrays.asList(
        new User(1, "xw", "男"),
        new User(2, "zgx", "男"),
        new User(3, "gg", "男"),
        new User(4, "whb", "男"),
        new User(5, "yda", "男"),
        new User(6, "bhm", "女")
);

List<User> userList2 = new ArrayList<>();
userList1.stream().filter(user -> user.getId() > 2).forEach(userList2::add);
log.info(userList2.toString());

userList1.stream().filter(user -> 					         user.getName().equals("xw")).forEach(System.out::println);

HashMap<String, Optional<User>> userHashMap = new HashMap<>();
Optional<User> man = userList1.stream().filter(user -> user.getSex().equals("男")).findFirst();
        userHashMap.put("man", man);
        log.info(userHashMap.toString());

3.聚合(max/min/count)

maxmincount这些字眼你一定不陌生,没错,在mysql中我们常用它们进行数据统计。Java stream中也引入了这些概念和用法,极大地方便了我们对集合、数组的数据统计工作。

max、min、count

 // max & min & count
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 89, 9, 0, 10, 20, 30);

Optional<Integer> max = list.stream()
        .max(Comparator.comparing(Integer::intValue));
log.info(String.format("最大值是:%d", max.get()));

Optional<Integer> min = list.stream()
        .min(Comparator.comparing(value -> value.intValue()));
log.info(String.format("最小值是:%d", min.get()));

Integer count1 = Math.toIntExact(list.stream().count());
log.info(String.format("list总元素量1为:%d", count1));

Integer count2 = Math.toIntExact(list.stream().filter(value -> value > 5).count());
log.info(String.format("list元素值大于5的个数:%d", count2));


List<User> userList = Arrays.asList(
        new User(1, "xw", "男", 22),
        new User(2, "zgx", "男", 22),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 22),
        new User(7, "lwn", "女", 22)
);
Optional<User> ageMax = userList.stream().max(Comparator.comparing(value -> value.getAge()));
log.info(String.format("年龄最大的是:%s", ageMax.get()));

Optional<User> ageMin = userList.stream().filter(user -> user.getSex().equals("男")).min(Comparator.comparing(User::getAge));
log.info(String.format("性别为男且年龄最小的:%s", ageMin.get()));

Integer count3 = Math.toIntExact(userList.stream().filter(user -> user.getAge() > 22).count());
log.info(String.format("年龄大于22的用户数量为:%d", count3));

4.映射(map/flatMap)

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。分为mapflatMap

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

map

// map
List<Integer> list1 = Arrays.asList(1, 3, 5, 6, 7, 8, 0, 10, 20, 22, 39);
List<Integer> collect1 = list1.stream().filter(value -> value > 7).collect(Collectors.toList());
log.info(String.format("list1元素值大于7的有: %s", collect1));

List<String> list2 = Arrays.asList("xw", "sjdk", "sf", "jk", "hoksh", "shdfj", "jhgkj");
List<String> collect2 = list2.stream().map(String::toUpperCase).collect(Collectors.toList());
log.info(String.format("list2元素值全转大写,结果:%s", collect2));

List<User> userList1 = Arrays.asList(
        new User(1, "xw", "男", 22),
        new User(2, "zgx", "男", 22),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 22),
        new User(7, "lwn", "女", 22),
        new User(8, "ksj", "女", 22)
);
List<User> userList2 = userList1.stream()
        .map(user -> {
            if (user.getSex().equals("女")) {
                user.setAge(user.getAge() - 2);
            }
            user.setName(user.getName().toUpperCase());
            return user;
        })
        .filter(user -> user.getAge() > 19 && user.getSex().equals("女"))
        .collect(Collectors.toList());
log.info(String.format("修改结果为:%s", userList2));

flatMap

// flatMap
List<String> stringList = userList1.stream()
        .flatMap(user -> {
            Stream<String> stream = Arrays.stream(user.toString().split("="));
            return stream;
        })
        .collect(Collectors.toList());
log.info(String.format("flatMap处理前:%s", userList1));
log.info(String.format("flatMap转换结果:%s", stringList));

5.归约(reduce)

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和求乘积求最值操作。

// 求和
List<Integer> list1 = Arrays.asList(1, 3, 5, 2, 1, 5, 89, 23, 89, 23, 34);
Integer sum = list1.stream().reduce(0, Integer::sum);
log.info(String.format("list1中各元素之和:%d", sum));

// 求积
List<Integer> list2 = Arrays.asList(1, 2, 4);
Optional<Integer> product = list2.stream().reduce((x, y) -> x * y);
log.info(String.format("list中2各元素之积:%d", product.get()));

// 求最大值1
Optional<Integer> max1 = list1.stream().reduce(Integer::max);
log.info(String.format("list1中的最大值是:%d", max1.get()));

// 求最大/小值2
Optional<Integer> min1 = list1.stream().reduce((x, y) -> x < y ? x : y);
log.info(String.format("list1中的最小值:%d", min1.get()));
List<User> userList1 = Arrays.asList(
        new User(1, "xw", "男", 22),
        new User(2, "zgx", "男", 22),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);

Integer maxAge1 = userList1.stream().reduce(0, (maxAge, user) -> maxAge > user.getAge() ? maxAge : user.getAge(), Integer::max);
log.info(String.format("年龄最大是:%d", maxAge1));

Optional<Integer> max2 = userList1.stream().map(User::getAge).reduce(Integer::max);
Optional<Integer> max3 = userList1.stream().map(User::getAge).reduce((x, y) -> x > y ? x : y);
log.info(String.format("年龄最大是:%d", max2.get()));
log.info(String.format("年龄最大是:%d", max3.get()));

Integer stringMaxLength = userList1.stream()
        .filter(user -> user.getAge() > 22 && user.getAge() < 25)
        .flatMap(user -> {
            Stream<String> newStream = Arrays.stream(user.toString().split("="));
            return newStream;
        })
        .collect(Collectors.toList())
        .stream().map(String::toUpperCase)
        .reduce(0, (maxLength, string) -> maxLength > string.length() ? maxLength : string.length(), Integer::max);

log.info(String.format("最大字符串长度为:%s", stringMaxLength));

6.收集(collect)

collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

collect主要依赖java.util.stream.Collectors类内置的静态方法。

6.1归集(toList/toSet/toMap)

因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toListtoSettoMap比较常用,另外还有toCollectiontoConcurrentMap等复杂一些的用法。

toList

List<Integer> list1 = Arrays.asList(1, 2, 8, 0, 9, 0, 1, 23, 32, 37, 49, 48);
List<Integer> collect1 = list1.stream().filter(value -> value > 5).collect(Collectors.toList());
log.info(String.format("list1中收集>5的结果为:%s", collect1));

toSet

Set<Integer> collect2 = list1.stream().filter(value -> value < 5).collect(Collectors.toSet());
log.info(String.format("list1中收集<5的结果为:%s", collect2));
collect2.forEach(value -> {System.out.print(value + " ");

toMap

List<User> userList1 = Arrays.asList(
        new User(1, "xww", "男", 22),
        new User(2, "zgx", "男", 22),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);

Map<String, User> userMap = userList1.stream()
         .filter(user -> user.getSex().equals("女"))
         .collect(Collectors.toMap(User::getName, user -> user));
log.info(String.format("性别为女的用户转map:%s", userMap));

6.2 统计(count/averaging)

Collectors提供了一系列用于数据统计的静态方法:

  • 计数:count
  • 平均值:averagingIntaveragingLongaveragingDouble
  • 最值:maxByminBy
  • 求和:summingIntsummingLongsummingDouble
  • 统计以上所有:summarizingIntsummarizingLongsummarizingDouble
List<Integer> list = Arrays.asList(1, 2, 3, 2, 5, 3, 9, 8, 7, 6, 29, 10, 22);

// count
long count = list.stream().filter(value -> value > 10).count();
log.info(String.format("list中元素>10的个数为:%d", count));

// average
Double average = list.stream().filter(value -> value > 1).collect(Collectors.averagingInt(Integer::intValue));
log.info(String.format("list中元素>1的元素平均值为:%.2f", average));

List<User> userList1 = Arrays.asList(
        new User(1, "xww", "女", 22),
        new User(2, "zgx", "男", 22),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);

Double averageAge = userList1.stream()
        .filter(user -> user.getSex().equals("男"))
        .map(User::getAge)
        .collect(Collectors.averagingInt(Integer::intValue));
log.info(String.format("男用户的平均年龄为:%d 岁", averageAge.intValue()));

// mapToInt
int ageSum = userList1.stream()
        .filter(user -> user.getSex().equals("女"))
        .mapToInt(User::getAge)
        .sum();
log.info(String.format("女用户的年龄之和为:%d", ageSum));

// summarizingInt 统计 计数、总和、最小值、平均值、最大值
IntSummaryStatistics recording = userList1.stream()
        .filter(user -> user.getSex().equals("男"))
        .collect(Collectors.summarizingInt(User::getAge));
log.info(String.format("记录所有男用户的年龄各项值,结果为:%s", recording));

6.3 分组(partitioningBy/groupingBy)

  • 分区:将stream按条件分为两个Map,比如员工按薪资是否高于8000分为两部分。
  • 分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
partitioningBy
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 20, 37, 49, 243, 30);

// partitioningBy
Map<Boolean, List<Integer>> collect1 = list.stream()
        .collect(Collectors.partitioningBy(value -> value > 20));
log.info(String.format("元素值是否大于20进行分组,结果为:%s", collect1));

collect1.forEach((key, value) -> {
    log.info(String.format("元素值是否大于20进行分组,结果为:%s:%s", key, value));
});

groupingBy

List<User> userList = Arrays.asList(
        new User(1, "xww", "女", 22),
        new User(2, "zgx", "男", 21),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);

// groupingBy
Map<String, List<User>> collect2 = userList.stream()
        .collect(Collectors.groupingBy(User::getSex));
log.info(String.format("根据性别对用户进行分组,结果为:%s", collect2));

collect2.forEach((key, user) -> {
    log.info(String.format("根据性别对用户进行分组,结果为:%s:%s", key, user));
});

6.4 接合(joining)

joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 20, 37, 49, 243, 30);
String collect = list.stream()
        .map(Object::toString)
        .collect(Collectors.joining("——"));
log.info(String.format("joining测试结果为:%s", collect));

7.排序(sorted)

sorted,中间操作。有两种排序:

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):Comparator排序器自定义排序
List<User> userList1 = Arrays.asList(
        new User(1, "xw", "女", 22),
        new User(2, "zgx", "男", 21),
        new User(3, "whb", "男", 23),
        new User(4, "gg", "男", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);

// sorted
List<User> userList2 = userList1.stream()
        .sorted(Comparator.comparing(User::getAge))
        .collect(Collectors.toList());
log.info(String.format("按照年龄排序,结果为:%s", userList2));

// 从小到大,正序
List<String> userName1 = userList1.stream()
        .sorted(Comparator.comparing(User::getAge))
        .map(User::getName)
        .collect(Collectors.toList());
log.info(String.format("根据年龄从小到大排序:%s", userName1));

// 从大到小,倒序
List<String> userName2 = userList1.stream()
        .filter(user -> user.getSex().equals("男"))
        .sorted(Comparator.comparing(User::getAge).reversed())
        .map(User::getName)
        .collect(Collectors.toList());
log.info(String.format("男用户根据年龄从大到小排序:%s", userName2));

8.提取/组合

流也可以进行合并去重限制跳过等操作。

1.去重排序

List<Integer> list = Arrays.asList(1, 2, 4, 4, 10, 9, 6, 8, 6, 2, 3, 7, 5);
List<Integer> collect = list
        .stream()
        .distinct()
        .sorted(Comparator.comparing(Integer::intValue))
        .collect(Collectors.toList());
collect.forEach(x -> System.out.print(x+" ")); // 1 2 3 4 5 6 7 8 9 10

存在重复数据的问题,这里使用stream流的衍生功能,去除一个对象中的部分元素的重复如下:

List<User> userList = Arrays.asList(
        new User(1, "xw", "女", 21),
        new User(2, "zgx", "男", 21),
        new User(3, "whb", "男", 23),
        new User(4, "gag", "男", 30),
        new User(4, "gbg", "男", 30),
        new User(4, "gcg", "女", 30),
        new User(5, "yda", "男", 22),
        new User(6, "bhm", "女", 23),
        new User(7, "lsn", "女", 22),
        new User(8, "ksj", "女", 22)
);
ArrayList<User> collect1 = userList.stream().collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(
                                Comparator.comparing(
                                        User::getId))), ArrayList::new));

多个字段或者多个条件去重

ArrayList<User> collect2 = userList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(
                        Comparator.comparing(user->user.getName() + ";" + user.getId()))), ArrayList::new)

以上使用到了collectingAndThen()根据属性进行去重的操作,进行结果集的收集,收集到结果集之后再进行下一步的处理。在这个去重操作中还用到了toCollection、TreeSet两个操作。

public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,Function<R,RR> finisher)

看源码中需要传的参数有两个,第一个参数是Collector的子类,所以Collectors类中的大多数方法都能使用,比如:toList(),toSet(),toMap()等,当然也包括collectingAndThen()。第二个参数是一个Function函数,也是去重的关键,用到的ArrayList::new调用到了ArrayList的有参构造。Function函数是R apply(T t),在第一个参数downstream放在第二个参数Function函数的参数里面,将结果设置为t。对于toCollection是一个通用的方法,满足treeSet收集集合,再传入需要根据某个属性进行比较的比较器,就能达到去重的效果。

2.限制长度(limit)

List<Integer> list = Arrays.asList(1, 2, 7, 3, 2, 2, 3, 4, 5, 2, 5, 6, 7, 8, 9, 0, 12);
List<Integer> collect1 = list
        .stream()
        .distinct()
        .sorted(Comparator.comparing(Integer::intValue))
        .limit(6)
        .collect(Collectors.toList());
collect1.forEach(x -> System.out.print(x + " "));

3.跳过(skip)

// 跳过前几项
List<Integer> list = Arrays.asList(1, 2, 7, 3, 2, 2, 3, 4, 5, 2, 5, 6, 7, 8, 9, 0, 12);
List<Integer> collect2 = list
        .stream()
        .distinct()
        .sorted(Comparator.comparing(Integer::intValue))
        .skip(3)
        .limit(6)
        .collect(Collectors.toList());
collect2.forEach(x -> System.out.print(x + " ")); 

标签:info,java,Stream,stream,练习,22,User,new,user
From: https://www.cnblogs.com/xw1203/p/16846833.html

相关文章

  • 利用java数组实现栈
    栈作为被广泛使用的数据结构,是在一个特定范围的存储单元中存储的数据,这些数据可以重新被取出使用,与线性表相比,它们的插入和删除受到更多的约束和限定,所以又称为限定性的线性......
  • nginx的upstream配置backup和check方法
    server{  listen         80;  server_name      ocean.xxxx;  access_log       /app/tengine_log/logs/oce......
  • Java实现 Serializable 序列化
    深度理解Java实现Serializable序列化概念把对象转换为直接序列的过程叫对象的序列化把字节序列恢复为对象的过程叫对象的反序列化用途对象持久化跨网络数据交换,远程过程调......
  • 初识java爬虫
    早上闲来无事,先总结一下昨天学到的最基本的的爬虫。首先说爬虫,其实就是向要爬取的网站发送一个http请求,取得反馈数据,然后解析数据,获得我们想要的数据。简单来说需要两步:......
  • dubbo java.nio.channels.ClosedChannelException、com.alibaba.dubbo.remoting.Remot
    客户端错误:com.alibaba.dubbo.rpc.RpcException:Invokeremotemethodtimeout.method:searchUser,provider:...cause:Waitingserver-sideresponsetimeoutbyscan......
  • 宜立方商品管理课后练习
    这段时间在做传智播客的宜立方商城项目,在此将视频里的课后练习写出来分享一下目录​​编辑​​​​批量删除​​​​上下架​​编辑按思路先找到JS代码里对应的URL,在分析JS......
  • JavaScript语法逻辑运算符和JavaScript三元运算符
    5.逻辑运算符 &&||! *其他类型转boolean:1.number:0或NaN为假,其他为真2.string:除了空字符串(""),其他都是true......
  • JavaWeb学习(四)期中考试总结(方框形式超链接,对修改页面进行优化,多条件模糊查询、输入长
    一、方框形式超链接 <inputtype="button"value="注册"onclick="location.href='zhuce.jsp'"/>  二、对修改页面进行优化<tr><td>活动主题(不超过20个汉......
  • unity3d:protobuf .java转.cs
    服务器端定义好protobuf结构,放unity编辑器中生成.cs的结构usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEditor;usingSystem......
  • crontab定时清理文件,java日志,es记录等
    简单运维开发环境硬件配置小,经常要清理空间.写个简单的清理脚本去运维.清理java日志.#cleanLog.sh#日志目录LOG_DIR=/path/to/logcd$LOG_DIR#历史日志......