Stream API

Stream API 主要操作:

筛选与切片
filter(Predicate)   筛选元素,从流中排除不满足Predicate的某些元素
limit(n)            截断流,使其元素不超过给定数量
skip(n)             跳过前面n个元素,若元素不足n个,则返回空流
distinct()          去重,通过流所生成元素的hashCode()与equals()去除重复元素

实体类

public class User {

    private String name;  // 姓名
    private String age;  // 年龄
    private double salary; // 薪水
    private Status status; // 工作状态:FREE 空闲, BUSY 繁忙 INVOCATION 休假

    public enum Status {
        BUSY, FREE, INVOCATION;
    }
    
    public User(){
        
    }

    public User(String name, String age, double salary, Status status) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }
    
    // Getter Setter equals hashCode toString
    
}
         List<User> list = Arrays.asList(
                new User("张三", 21, 6000, User.Status.BUSY),
                new User("李四", 23, 7000, User.Status.FREE),
                new User("王五", 25, 6000, User.Status.INVOCATION),
                new User("赵六", 21, 10000, User.Status.BUSY),
                new User("赵六", 21, 10000, User.Status.BUSY)
        );

        // filter 筛选出BUSY状态的员工
        list.stream()
                .filter(u -> User.Status.BUSY.equals(u.getStatus()))
                .forEach(System.out::println);
                
        /*  结果:
            User{name='张三', age='21', salary=6000.0, status=BUSY}
            User{name='赵六', age='21', salary=10000.0, status=BUSY}
            User{name='赵六', age='21', salary=10000.0, status=BUSY}      
        */  

        // 筛选出工资等于6000的一个员工
        list.stream()
                .filter(u -> u.getSalary() == 6000)
                .limit(1)
                .forEach(System.out::println);
                
        /*  结果:
            User{name='张三', age='21', salary=6000.0, status=BUSY}   
        */  


        // 筛选工资等于6000,不是第一个员工的员工
        list.stream()
                .filter(u -> u.getSalary() == 6000)
                .skip(1)
                .forEach(System.out::println);
                
        /*  结果:
            User{name='王五', age='25', salary=6000.0, status=INVOCATION} 
        */          

        // 员工列表去重
        list.stream()
                .distinct()
                .forEach(System.out::println);
                
        /*  结果:
            User{name='张三', age='21', salary=6000.0, status=BUSY}
            User{name='李四', age='23', salary=7000.0, status=FREE}
            User{name='王五', age='25', salary=6000.0, status=INVOCATION}
            User{name='赵六', age='21', salary=10000.0, status=BUSY}
        */        
映射
map(Function<T, R>)       提取元素,使用Function应用到每个元素
flatMap(Function<T, Stream<R>>)   提取元素,应用每个元素得到每一个新的Stream,然后将这些Stream合并成新的Stream
    public static void test() {
        List<String> list = Arrays.asList("abc", "def", "ghi");

        // 将每个元素(这里指的每个元素是指"abc", "def"这种),转换成大写
        list.stream()
                .map(String::toUpperCase)
                .forEach(System.out::print);
        
        /*  结果:
            ABCDEFGHI
        */            

        // 提取所有字符
        // 步骤:应用每个元素,比如"abc"将其转换成Stream<Charactor>,然后得到三个Stream<Charactor>,最终合并到一个新的Stream<Character>,类似于list.addAll
        list.stream()
                .flatMap(Test::strToCharator)  // ==> .flatMap(s -> strToCharator(s))
                .forEach(System.out::print);    
                        
        /*  结果:
            abcdefghi
        */ 
    }

    public static Stream<Character> strToCharator(String s){
        List<Character> list = new ArrayList<>();
        for (char c : s.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }        

重点说下区别:

Stream<Stream<Character>> characterStream = list.stream()
        .map(Test::strToCharator);
characterStream.forEach(s -> s.forEach(System.out::println));
// s = Stream<Character> ,所有需要再迭代遍历一次,共两次   
// 变化为 "abc","bcd", "ghi" --> {a, b, c}, {b, c, d}, {g, h , i} --> {  {a, b, c}, {b, c, d}, {g, h , i}  }


Stream<Character> characterStream2 = list.stream()
        .flatMap(Test::strToCharator);
characterStream2.forEach(System.out::println);
// 变化为 "abc","bcd", "ghi" -->  {a, b, c }, {b, c, d}, {g, h , i} -->  {a,b,c,d,e,f,g,h,i}


类比于List list1, List list2
list1.add(list2)     // 将list2作为list1的元素
list1.addAll(list2)  // 将list2中所有元素放入到list1中
排序
sorted()                自然排序
sorted(Comparator)      自定义排序
        List<String> list = Arrays.asList("bcd", "abe", "afa");

        // 自然排序
        list.stream()
                .sorted()
                .forEach(System.out::println);

        // 按照string排序
        list.stream()
                .sorted(String::compareTo)
                .forEach(System.out::println);

        // 按照第二个元素排序        
        list.stream()
                .sorted((s1, s2) -> Character.valueOf(s1.charAt(1)).compareTo( Character.valueOf(s2.charAt(1))))
                .forEach(System.out::println);

        // 等于上面,使用工具类  Comparator 更加方便      
        list.stream()
                .sorted(Comparator.comparing(s -> s.charAt(1)))
                .forEach(System.out::println);
查找与匹配
allMatch        流中所有元素都匹配成功,返回true
anyMatch        流中匹配一个元素即返回true
noneMatch       流中所有元素都不匹配,返回true,与allMatch相反
findFirst       返回流中匹配的第一个元素
findAny         返回流中匹配到的第一个元素,由于可能是parallelStream并行方式,所以不等于findFirst
count           返回流中元素个数
max             返回流中最大值
min             返回流中最小值
        List<User> list = Arrays.asList(
                new User("张三", 21, 6000, User.Status.BUSY),
                new User("李四", 23, 7000, User.Status.FREE),
                new User("王五", 25, 6000, User.Status.INVOCATION),
                new User("赵六", 21, 10000, User.Status.BUSY)
        );

        // 1. 所有员工是否都处于BUSY状态
        boolean b = list.stream().allMatch(u -> User.Status.BUSY.equals(u.getStatus()));  // ==> false
        // 更好的方式: list.stream().map(User::getStatus).allMatch(User.Status.BUSY::equals)

        // 2. 至少有一个员工处理BUSY状态
        boolean b2 = list.stream().map(User::getStatus).anyMatch(User.Status.BUSY::equals);  // ==> true

        // 3. 所有员工都不处于BUSY状态
        boolean b3 = list.stream().map(User::getStatus).noneMatch(User.Status.BUSY::equals);  // ==> false

        // 4. 找出处于BUSY状态的第一个员工
        Optional<User> firstUser = list.stream().filter(u -> User.Status.BUSY.equals(u.getStatus())).findFirst();  // firstUser.get() 张三

        // 5. 找出任意一个处于BUSY状态的员工
        Optional<User> anyUser = list.parallelStream().filter(u -> User.Status.BUSY.equals(u.getStatus())).findAny(); // anyUser.get() 赵六

        // 6. 处于BUSY状态的员工数量
        long count = list.stream().map(User::getStatus).filter(User.Status.BUSY::equals).count();  // ==> 2

        // 7. 找到工资最高的员工
        Optional<User> maxSalaryUser = list.stream().max(Comparator.comparingDouble(User::getSalary)); // maxSalaryUser.get() 赵六

        // 8. 找到年龄最小的员工
        Optional<User> minAgeUser = list.stream().min(Comparator.comparingInt(User::getAge)); // minAgeUser.get() 张三
归约与收集
reduce(T identity, BinaryOperator) / reduce(BinaryOperator)   可以将流中的元素反复结合起来,得到一个值
collect         将流转换成其他形式,接收

BinaryOperator extends BiFunction 所以是 T, T, R, 两个参数,一个返回值

reduce
        List<User> list = Arrays.asList(
                new User("张三", 21, 6000, User.Status.BUSY),
                new User("李四", 23, 7000, User.Status.FREE),
                new User("王五", 25, 6000, User.Status.INVOCATION),
                new User("赵六", 21, 10000, User.Status.BUSY)
        );

        int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // 1. 数组所有元素求和
        int sum = Arrays.stream(arr).reduce(0, (x, y) -> x + y); // 55
        // 说明:这里identity=0,指代第一次运算的x=0,y=数组第一个元素,也就是1,如果identity=2,那么第一次就是x=2, y=1, 那么最终结果=56
        // 由于有第一次运算默认值,所以这里一定有返回值,所以设计为返回int,假设没有初始值,也就是下面这种,不确定元素是否足够,返回Optional

        OptionalInt optionalInt = Arrays.stream(arr).reduce((x, y) -> x + y); // optionalInt.getAsInt() == 55
        // OptionalInt 为 Optional 专门为int的包装类,比Optional<Integer>性能更好,减少装箱拆箱操作

        // 2. 计算所有员工工资总和
        Optional<Double> sumSalary = list.stream().map(User::getSalary).reduce(Double::sum); // sumSalary.get()

map-reduce 这种思想应用很广,比如hadoop,提取然后计算

collect

        List<User> list = Arrays.asList(
                new User("张三", 21, 6000, User.Status.BUSY),
                new User("李四", 23, 7000, User.Status.FREE),
                new User("王五", 25, 6000, User.Status.INVOCATION),
                new User("赵六", 21, 10000, User.Status.BUSY)
        );
        
                // ---------------------- 转换为集合 -------------------
        // collect(Collector),可以工具类Collectors生成Collector
        // 1. 获取员工姓名列表
        // 返回一个list
        List<String> userNameList = list.stream().map(User::getName).collect(Collectors.toList());
        // 返回set
        Set<String> userNameSet = list.stream().map(User::getName).collect(Collectors.toSet());
        // 返回hashSet
        HashSet<String> userNameHashSet = list.stream().map(User::getName).collect(Collectors.toCollection(HashSet::new));

        
        // ---------------------- 计算 ------------------------
        // 2. 得到员工数量
        // 总数
        Long count = list.stream().collect(Collectors.counting()); // == list.stream().count()
        // 工资大于5000员工数量
        Long salaryConditionCount = list.stream().map(User::getSalary).filter(s -> s > 5000).collect(Collectors.counting()); // == filter().count()

        // 3. 所有员工平均工资
        Double averagSalary = list.stream().collect(Collectors.averagingDouble(User::getSalary));
        // 4. 最高/最低工资
        Optional<Double> maxSalary = list.stream().map(User::getSalary).collect(Collectors.maxBy(Double::compare)); // == map().max()


        // -------------------- 分组 --------------------------
        // 类似于SQL中的group by
        // 5. 根据工作状态分组 (单级分组) { BUSY: List<User>, FREE: List<User> }
        Map<User.Status, List<User>> userMapByStatus = list.stream().collect(Collectors.groupingBy(User::getStatus));
        // 6. 先根据工作状态分组,再根据年龄分组 (多级分组){ BUSY: {21 : List<User>, 23 : List<User>}, FREE : { 25 : List<User>, 26 : List<User> } }
        Map<User.Status, Map<Integer, List<User>>> userMapByStatusAndAge = list.stream()
                .collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy(User::getAge)));
        // 7. 更多级分组
        Map<User.Status, Map<Integer, Map<Double, List<User>>>> userMapByStatusAndAgeAndSalary = list.stream()
                .collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getSalary))));
        // 8. 自定义分组,先按工作状态分组,再自定义下一次分组key,比如小于30岁,key为青年,大于30岁,key为中年
        // ==> { BUSY : { "青年" : List<User>, "老年" : List<User> }  }
        list.stream().collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy(u -> {
            User user = (User)u;
            if (user.getAge() < 30) {
                return "青年";
            } else {
                return "中年";
            }
        })));

        
        // ------------------ 分区 ------------------------
        // 特殊情况下的分组形式,分组条件结果为true/false,即 { true : List<xx>, false : List<xx> }
        // 9. 将工资大于6000的分一个区,小于等的分一个区 ==> {true : List<工资大于6000的User>, false : List<工资小于等于6000的User> }
        Map<Boolean, List<User>> partitionSalaryMap = list.stream().collect(Collectors.partitioningBy(u -> u.getSalary() > 6000));


        // ------------------ 统计 -----------------------
        // 返回一个统计结果相关的操作类,可用来得到最大值,最小值等等,当要获取一个集合的各项情况时,这种方式比较好,必须要生成多次流操作获取
        DoubleSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingDouble(User::getSalary));
        double summaryStatisticsSum = summaryStatistics.getSum();  // 总和,工资总数
        long summaryStatisticsCount = summaryStatistics.getCount(); // 总的个数,员工数
        double summaryStatisticsMax = summaryStatistics.getMax();  // 最高工资
        double summaryStatisticsMin = summaryStatistics.getMin(); // 最低工资
        double summaryStatisticsAverage = summaryStatistics.getAverage(); // 平均工资

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
本项目是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。该系统主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者,包含项目源码、数据库脚本、项目说明等,有论文参考,可以直接作为毕设使用。 后台框架采用SpringBoot,数据库使用MySQL,开发环境为JDK、IDEA、Tomcat。项目经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。 该系统的功能主要包括商品管理、订单管理、用户管理等模块。在商品管理模块中,可以添加、修改、删除商品信息;在订单管理模块中,可以查看订单详情、处理订单状态;在用户管理模块中,可以注册、登录、修改个人信息等。此外,系统还提供了数据统计功能,可以对销售数据进行统计和分析。 技术实现方面,前端采用Vue框架进行开发,后端使用SpringBoot框架搭建服务端应用。数据库采用MySQL进行数据存储和管理。整个系统通过前后端分离的方式实现,提高了系统的可维护性和可扩展性。同时,系统还采用了一些流行的技术和工具,如MyBatis、JPA等进行数据访问和操作,以及Maven进行项目管理和构建。 总之,本系统是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。系统经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值