剑指高效编程之流编程

流编程

实战案例:集合与流操作对比

分别使用集合操作及Stream流操作,完成对实际应用场景中数据处理。直观感受流操作带来的便捷性

需求:
1.想看看购物车里有什么商品
2.图书类都给买
3.其余商品中买两件最贵的
4.只需要两件商品的名称和总价

传统操作

/**
     * 以最原始的集合操作实现以上的需求
     */

    @Test
    public void  oldCartHandle(){
        /**
         * 1.打印所有商品
         */
        List<Sku> cartSkuList = CartService.getCartSkuList();

        /**
         * 1.打印所有商品
         */
        for (Sku sku:cartSkuList) {
            System.out.println(JSON.toJSONString(sku,true));
        }

        /**
         * 2.图书类都给买
         */
        List<Sku> notBooks = new ArrayList<Sku>();
        for (Sku sku:cartSkuList) {
            if (!(sku.getSkuCategory().equals(SkuCategoryEnum.BOOKS))){
                notBooks.add(sku);
            }
        }

        /**
         * 3.其余商品中买两件最贵的
         * 3.1 排序
         */
        notBooks.sort(new Comparator<Sku>() {
            @Override
            public int compare(Sku sku1, Sku sku2) {
                if (sku1.getTotalPrice() > sku2.getTotalPrice()){
                    return -1;
                }else if(sku1.getTotalPrice() < sku2.getTotalPrice()){
                    return 1;
                }else {
                    return 0;
                }
            }
        });

        /**
         * 3.2 只需要前两个
         */
        List<Sku> top2SkuList = new ArrayList<Sku>();
        for (int i = 0; i < 2; i++) {
            top2SkuList.add(notBooks.get(i));
        }

        /**
         * 4.只需要两件商品的名称和总价
         */

        Double money = 0.0;
        for (Sku sku:top2SkuList) {
            money += sku.getTotalPrice();
        }

        /**
         * 获取两件商品名称
         */
        List<String> resultSkuNameList = new ArrayList<String>();
        for (Sku sku: top2SkuList) {
            resultSkuNameList.add(sku.getSkuName());
        }

        /**
         * 打印输出结果
         */
        System.out.println(JSON.toJSONString(resultSkuNameList,true));
        System.out.println("总价="+money);



    }

Stream流操作

/**
     * 以Stream流操作实现以上的需求
     */
    @Test
    public void  newCartHandle(){

        AtomicReference<Double> money = new AtomicReference<>(Double.valueOf(0.0));

        List<String> resultSkuNameList = CartService.getCartSkuList()
                .stream()
                /**
                 * 1.打印商品信息
                 */
                .peek(sku -> System.out.println(JSON.toJSONString(sku, true)))
                /**
                 * 2.过滤出图书类信息
                 */
                .filter(sku -> !SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
                /**
                 * 3.对商品进行排序
                 */
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
                /**
                 * 4.取出前两个商品
                 */
                .limit(2)
                /**
                 * 金额累加
                 */
                .peek(sku -> money.set(money.get() + sku.getTotalPrice()))
                /**
                 * 商品名称
                 */
                .map(sku -> sku.getSkuName())
                /**
                 * 结果收集
                 */
                .collect(Collectors.toList());

        /**
         * 打印输出结果
         */
        System.out.println(JSON.toJSONString(resultSkuNameList,true));
        System.out.println("总价="+money.get());
    }

流是什么?

  • JDK1.8引入的新成员,以声明式方式处理集合数据
  • 将基础操作链接起来,完成复杂的数据处理流水线
  • 提供透明的并行处理

定义:从支持数据处理操作的源生成的元素序列

流与集合的区别

  • 集合面向存储,流面向计算
  • 集合可以遍历多次,流只能遍历一次
  • 集合需要外部迭代,流内部迭代

流的组成

数据源、中间操作、终端操作
在这里插入图片描述

流操作的分类

在这里插入图片描述
在这里插入图片描述

实战案例:流的使用

常用的中间操作

/**
 * 演示流的各种中间操作
 */
public class StreamOperator {

    List<Sku> list ;

    @Before
    public void init(){
        list = CartService.getCartSkuList();
    }

    /**
     * filter 使用:过滤掉不符合断言判断的数据
     */
    @Test
    public void filterTest(){
        list.stream()

                //filter
                .filter(sku -> SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));
    }

    /**
     * map 使用:将一个元素转换为另一个元素
     */
    @Test
    public void mapTest(){
        list.stream()

                // map
                .map(sku -> sku.getSkuName())
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));
    }


    /**
     * flatMap 使用:将一个对象转换成流
     */
    @Test
    public void flatMapTest(){
        list.stream()
                //flatMap  扁平化 map
                .flatMap(sku -> Arrays.stream(sku
                .getSkuName().split("")))
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));
    }


    /**
     * peek 使用:对流中元素进行遍历操作,与Foreach类似,但不会销毁流元素
     * foreach 与 peek是交替执行的
     */
    @Test
    public void peekTest(){
        list.stream()
                //peek()
                .peek(sku -> System.out.println(sku.getSkuName()))
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));

    }

    /**
     * sorted: 排序操作,可选择自然排序或指定排序规则,有状态操作
     */
    @Test
    public  void sortTest(){
        list.stream()
                .peek(sku -> System.out.println(sku.getSkuName()))

                //sorted
                .sorted(Comparator.comparing(Sku::getTotalPrice))
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));
    }



    /**
     * dinstant: 去重操作,有状态操作
     */

    @Test
    public void dinstantTest(){
        list.stream()
                .map(sku -> sku.getSkuCategory())
                .distinct()
                .forEach(item -> System.out.println(JSON.toJSONString(item,true)));
    }



    /**
     * skip: 跳过前N条数据
     */
    @Test
    public void skipTest(){
        list.stream()
                .sorted(Comparator.comparing(Sku::getSkuPrice))
                //过滤掉前两条数据
                .skip(2)
                .forEach(item->System.out.println(JSON.toJSONString(item,true)));
    }



    /**
     * limit: 取前N条数据
     */
    @Test
    public void limitTest(){
        list.stream()
                .sorted(Comparator.comparing(Sku::getSkuPrice))

                //模拟分页   第一页,一页显示两条
                .skip( 1 * 2)
                .limit(2)
                .forEach(item->System.out.println(JSON.toJSONString(item,true)));
    }
    
}

常用的终端操作

/**
     * allMatch 使用: 终端操作,并且是一个短路操作,全部满足才会返回true
     */
    @Test
    public void allMatchTest(){
        boolean match = list.stream()

                .peek(sku -> System.out.println(sku.getSkuName()))
                //allMatch
                .allMatch(sku -> sku.getTotalPrice() > 100);
        System.out.println(match);
    }

    /**
     * anyMatchsh 使用:有一个满足就返回TRUE
     */
    @Test
    public void anyMatchshTest(){
        boolean anyMatch = list.stream()
                .anyMatch(sku -> sku.getTotalPrice() > 1000);
        System.out.println(anyMatch);
    }

    /**
     * noneMatch使用:所有的都没匹配上返回true
     */

    @Test
    public void noneMatchshTest(){
        boolean noneMatch = list.stream()
                .peek(sku -> System.out.println(sku.getSkuName()))
                .noneMatch(sku -> sku.getSkuPrice() > 10000);
        System.out.println(noneMatch);
    }
/**
     * findFirst使用:找到第一个元素
     */
    @Test
    public void findFirstTest(){
        Optional<Sku> first = list.stream()
                .findFirst();
        System.out.println(JSON.toJSONString(first.get(),true));
    }

    /**
     * findAny 使用:在并行操作上效率高于 findFirst
     */
    @Test
    public void findAnyTest(){
        Optional<Sku> any = list.stream()
                .findAny();
        System.out.println(JSON.toJSONString(any.get(),true));
    }


    /**
     * max 使用:获取最大值
     */
    @Test
    public void maxTest(){
        OptionalDouble max = list.stream()
                //获取总价
                //maptoDouble:将一个元素转化为double元素
                .mapToDouble(Sku::getSkuPrice)
                //获取总价最大值
                .max();
        System.out.println(JSON.toJSONString(max.getAsDouble(),true));
    }

    /**
     * min 使用:获取最小值
     */
    @Test
    public void minTest(){
        OptionalDouble min = list.stream()
                //获取总价
                //maptoDouble:将一个元素转化为double元素
                .mapToDouble(Sku::getSkuPrice)
                //获取总价最大值
                .min();
        System.out.println(JSON.toJSONString(min.getAsDouble(),true));
    }

    /**
     * count 使用:获取元素总数
     */
    @Test
    public void countTest(){
        long count = list.stream()
                .count();
        System.out.println(count);
    }
    

流的构建

  • 由值创建流
  • 由数组创建流
  • 由文件创建流
  • 由函数生成流

实战案例:演示流的四种构建形式


import org.junit.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 演示流的四种构建形式
 */
public class StreamConstructor {

    //由值创建流
    @Test
    public void streamFromValue(){
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
        integerStream.forEach(System.out :: println);
    }


    //由数组创建流
    @Test
    public void streamFromArray(){
        int [] number = {1,2,3,4,5,6};
        IntStream stream = Arrays.stream(number);
        stream.forEach(System.out :: println);
    }

    //由文件创建流
    @Test
    public void streamFromFile() throws IOException {
        Stream<String> lines = Files.lines(Paths.get("D:\\demo\\app\\src\\main\\java\\com\\ausware\\yaowenyu\\steam\\StreamConstructor.java"));
        lines.forEach(System.out :: println);
    }

    //由函数创建流
    @Test
    public void streamFromFunction(){

        //方式一:
//        Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
//        iterate.forEach(System.out::println);

        //方式二:
        Stream<Double> generate = Stream.generate(Math::random);
        generate.limit(100)
                .forEach(System.out::println);
    }


}

收集器简介

  • 将流中的元素累积成一个结果
  • 作用于终端操作 collect()上
  • collect/Collector/Collectors

预定义收集器功能

  • 将流元素归约和汇总为一个值
  • 将流元素分组
  • 将流元素分区

实战案例:预定义收集器


import com.alibaba.fastjson.JSON;
import com.ausware.yaowenyu.lambda.cart.CartService;
import com.ausware.yaowenyu.lambda.cart.Sku;
import org.junit.Test;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 常见预定义收集器使用
 */
public class StreamCollector {

    /**
     * toList 使用:将流转化为集合
     */
    @Test
    public void toListTest(){
        List<Sku> list = CartService.getCartSkuList();
        List<Sku> collect = list.stream()
                .filter(sku -> sku.getTotalPrice() > 1000)
                .collect(Collectors.toList());
        System.out.println(JSON.toJSONString(collect,true));

    }

    /**
     * group 使用:将流按照指定条件进行分组
     */
    @Test
    public void gruopTest(){
        List<Sku> list = CartService.getCartSkuList();
        Map<Enum, List<Sku>> collect = list.stream()
                .collect(Collectors.groupingBy(sku -> sku.getSkuCategory()));
        System.out.println(JSON.toJSONString(collect,true));
    }

    /**
     * partition 使用:将流按照指定条件进行分区
     */
    @Test
    public void partitionTest(){
        List<Sku> list = CartService.getCartSkuList();
        Map<Boolean, List<Sku>> collect = list.stream()
                .collect(Collectors.partitioningBy(sku -> sku.getTotalPrice() > 1000));
        System.out.println(JSON.toJSONString(collect,true));
    }



}

归约与汇总

  • 归约:将Stream 流中元素转换成一个,只返回一个

在这里插入图片描述

  • 在这里插入图片描述

reduce接口参数
在这里插入图片描述

实战案例:自定义归约
根据一批订单信息,计算平均商品价格


import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;

import java.util.ArrayList;

/**
 * 归约与汇总操作
 */
public class ReduceAndCollectTest {


    @Test
    public void reduceTest(){

        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        class Order{

            //订单编号
            private Integer id;

            //订单总金额
            private Double totalAmount;

            //商品数量
            private Integer productCount;
        }

        //准备数据
        ArrayList<Order> orders = new ArrayList<>();
        {
            orders.add(new Order(1,25.12,2));
            orders.add(new Order(2,12.26,4));
            orders.add(new Order(3,23.56,12));
            /**
             * 传统方式:
             * 1.计算商品数量
             * 2.计算商品总金额
             */

            /**
             * 汇总商品数量合总金额
             */
            Order reduce = orders.stream()
                    .parallel()
                    .reduce(
                            //初始化值
                            new Order(0, 0.0, 0),

                            //Stream中两个元素的计算逻辑
                            (Order order1, Order order2) -> {
                                System.out.println("执行 计算逻辑 方法!!!");
                                int productCount = order1.getProductCount() + order2.getProductCount();
                                double totalAmount = order1.getTotalAmount() + order2.getTotalAmount();
                                return new Order(0, totalAmount, productCount);
                            },

                            //并行情况下多个并行结果如何合并
                            (Order order1, Order order2) -> {
                                System.out.println("执行 合并 方法!!!");
                                int productCount = order1.getProductCount() + order2.getProductCount();
                                double totalAmount = order1.getTotalAmount() + order2.getTotalAmount();
                                return new Order(0, totalAmount, productCount);
                            });

            System.out.println(JSON.toJSONString(reduce,true));

        }
    }
}

  • 汇总:将Stream流中元素转换成一个容器

在这里插入图片描述

在这里插入图片描述

实战案例:自定义收集
根据一批订单信息,计算每个用户的平均商品价格

 @Test
    public void collectTest(){
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        class Order{

            //订单编号
            private Integer id;

            //订单总金额
            private Double totalAmount;

            //商品数量
            private Integer productCount;

            //账户
            private String account;
        }

        ArrayList<Order> orders = new ArrayList<>();
        {
            orders.add(new Order(1,25.12,2,"张三"));
            orders.add(new Order(2,12.26,4,"张三"));
            orders.add(new Order(3,23.56,12,"李四"));
        }

        /**
         * Map<用户账户,订单(商品数量和价格)>
         */
        HashMap<String, Order> collect = orders.stream()
                .parallel()
                .collect(
                        () -> {

                            System.out.println("执行 初始化容器");
                            return new HashMap<String, Order>();
                        }
                        , (HashMap<String, Order> map, Order newOrder) -> {

                            System.out.println("执行 新元素添加到容器 操作");

                            /**
                             * 新元素的账号已经在map中
                             */
                            String account = newOrder.getAccount();

                            //如果此账户已存在
                            if (map.containsKey(account)) {
                                Order order = map.get(account);
                                order.setProductCount(newOrder.getProductCount() + order.getProductCount());
                                order.setTotalAmount(newOrder.getTotalAmount() + order.getTotalAmount());
                            } else {
                                //如果不存在
                                map.put(account, newOrder);
                            }
                        },
                        (HashMap<String, Order> map1, HashMap<String, Order> map2) -> {


                            System.out.println("执行 并行结果合并 操作");
                            map2.forEach((key, value) -> {
                                map1.merge(key, value, (order1, order2) -> {

                                    //注意:一定要用map1做合并,因为最后collect返回的是map1
                                    return new Order(0,
                                            order1.getTotalAmount() + order2.getTotalAmount(),
                                            order1.getProductCount() + order2.getProductCount(),
                                            key);
                                });
                            });

                        });

        System.out.println(JSON.toJSONString(collect,true));
    }

collect接口参数

在这里插入图片描述

收集器接口

在这里插入图片描述

实战案例一:查找

班级中有20名学生,每名学生有5门课的考试成绩。其中缺考的科目分数字段为空。需要找出有缺考的学生都叫什么名字。


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 案例一
 */
public class CaseOne {

    /**
     * 考试成绩模型
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class ExamStudentScore{

        private String name;

        private Integer score;

        private String subject;

    }

    Map<String , List<ExamStudentScore>> studentMap = new HashMap<>();

    @Before
    public void init(){
        ArrayList<ExamStudentScore> examStudentScores1 = new ArrayList<>();
        examStudentScores1.add(new ExamStudentScore("张三",85,"语文"));
        examStudentScores1.add(new ExamStudentScore("张三",90,"数学"));
        examStudentScores1.add(new ExamStudentScore("张三",79,"英语"));
        studentMap.put("张三",examStudentScores1);

        ArrayList<ExamStudentScore> examStudentScores2 = new ArrayList<>();
        examStudentScores2.add(new ExamStudentScore("李四",80,"语文"));
        examStudentScores2.add(new ExamStudentScore("李四",null,"数学"));
        examStudentScores2.add(new ExamStudentScore("李四",null,"英语"));
        studentMap.put("李四",examStudentScores2);

        ArrayList<ExamStudentScore> examStudentScores3 = new ArrayList<>();
        examStudentScores3.add(new ExamStudentScore("王五",79,"语文"));
        examStudentScores3.add(new ExamStudentScore("王五",null,"数学"));
        examStudentScores3.add(new ExamStudentScore("王五",80,"英语"));
        studentMap.put("王五",examStudentScores3);

    }


    @Test
    public void findStudent(){

        studentMap.forEach((studentName, scoreList) -> {

            boolean anyMatch = scoreList.stream()
                    .anyMatch(score -> {

                        //anyMatch 找到任意一条符合条件的数据后就停止
                        //System.out.println(score);
                        return score.getScore() == null;
                    });

            if (anyMatch){
                System.out.println("此学生姓【"+studentName+"】有缺考情况!");
            }

        });
    }
}


实战案例二:去重

标签管理功能模块。允许用户批量添加标签,后台需要对标签去重,并且需要防止数据库中存在同名的标签。


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 案例二:
 */
public class CaseTwo {

    /**
     * 用户请求的创建标签模型
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class TagReqDTO{

        //标签名称
        private String name;

        //标签值
        private Integer age;
    }

    //从DB中查询出来的已经存在的标签名
    List<String> tagListFromDB = new ArrayList<String>();

    //用户请求的标签列表
    List<TagReqDTO> tagListFromReq = new ArrayList<TagReqDTO>();

    @Before
    public void init(){
        //数据库中存在的标签名列表
        tagListFromDB.add("李四");
        tagListFromDB.add("王五");
        tagListFromDB.add("赵六");
        //用户提交
        tagListFromReq.add(new TagReqDTO("张三",10));
        tagListFromReq.add(new TagReqDTO("李四",30));
        tagListFromReq.add(new TagReqDTO("张三",10));
    }

    @Test
    public void distinctTest(){
        tagListFromReq.stream()
                //true:通过测试,数据不过滤,false:未通过测试,数据被过滤
                .filter(tag -> tagListFromDB.contains(tag.getName()))
                //使用equals对元素进行比较
                .distinct()
                .forEach(tag->System.out.println(tag));
    }
}

实战案例三:扁平化

权限管理功能模块。查询某用户所有角色下所包含的权限名称。

package com.ausware.yaowenyu.steam.test;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Test;
import org.springframework.expression.spel.SpelEvaluationException;

import javax.management.relation.Role;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 案例三:
 */
public class CaseThree {


    /**
     * 角色数据模型
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Role{
        //权限列表
        private List<Permission> permissions;
    }

    /**
     * 权限
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Permission{

        /**
         * 权限名称
         */
        private String name;

    }

    /**
     * 用户角色列表
     */
    List<Role> roleList;

    @Before
    public void init(){

        roleList = new ArrayList<>();

        Role adminRole = new Role();
        List<Permission> adminPermissions = Lists.newArrayList(
                new Permission("删除"),
                new Permission("查看"),
                new Permission("导出")
        );
        adminRole.setPermissions(adminPermissions);

        Role userRole = new Role();
        ArrayList<Permission> userPermissions = Lists.newArrayList(
                new Permission("新建"),
                new Permission("修改"),
                new Permission("删除"),
                new Permission("查看")
        );
        userRole.setPermissions(userPermissions);

        roleList.add(adminRole);
        roleList.add(userRole);

    }

    @Test
    public void findPermission(){
        roleList.stream()

                //扁平化map
                .flatMap(role -> role.getPermissions().stream())
//                .peek(permission -> System.out.println("新的流元素:"+permission))
                .distinct()
                .forEach(permission -> System.out.println(permission));
//                .collect(Collectors.toList());
    }
}

实战案例四:分组

设计一个对外提供服务的接口,支持调用方传入多个账户编号查询订单。



import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.assertj.core.util.Lists;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 案例四:
 */
public class CaseFour {

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Order{
        private Integer orderId;
        private String accountId;
    }

    //模拟数据库查询
    public List<Order> selectFromDB(List<String> accountIds){
        List<Order> orderList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            orderList.add(new Order(i,accountIds.get(i % accountIds.size())));
        }
        return orderList;
    }


    /**
     * 接口
     * @param accountIds
     * @return
     */
    public Map<String ,List<Order>> queryOrderByAcoiuntIds(List<String> accountIds){

        return Optional.ofNullable(selectFromDB(accountIds))
                .map(List::stream)
                .orElseGet(Stream::empty)
                .collect(Collectors.groupingBy((order)->order.getAccountId()));

    }

    @Test
    public void test(){
        Map<String, List<Order>> stringListMap = queryOrderByAcoiuntIds(Lists.newArrayList("张三", "李四", "王五"));
        System.out.println(JSON.toJSONString(stringListMap,true));
    }


}

实战案例五:排序

在股票中,撮合交易的原则是一段时间内的交易申请,价格越高的先成交﹔价格一样,下单时间最早的先成交﹔价格和时间一致,交易量大的先成交﹔如果价格、时间和交易量都一致,机构优先成交,散户最后成交。 现有一批交易申请数据,需要确认交易先后顺序。



import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Before;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 案例五:
 */
public class CaseFive {


    /**
     * 交易实体模型
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Trade{
        //下单价格
        private BigDecimal price;
        //下单时间
        private LocalDateTime time;
        //下单量
        private Integer count;
        //下单类型:机构/个人
        private String type;
    }

    /**
     * 一段时间内的交易申请
     */
    List<Trade> trades;

    @Before
    public void init(){
        trades = new ArrayList<>();
        {
            trades.add(new Trade(new BigDecimal(100),LocalDateTime.now().plusSeconds(1),500,"机构"));
            trades.add(new Trade(new BigDecimal(101),LocalDateTime.now().plusSeconds(2),1,"个人"));
            trades.add(new Trade(new BigDecimal(101),LocalDateTime.now().plusSeconds(1),1,"个人"));
            trades.add(new Trade(new BigDecimal(100),LocalDateTime.now().plusSeconds(1),500,"个人"));
            trades.add(new Trade(new BigDecimal(101),LocalDateTime.now().plusSeconds(1),1,"个人"));
            trades.add(new Trade(new BigDecimal(100),LocalDateTime.now().plusSeconds(0),500,"个人"));
            trades.add(new Trade(new BigDecimal(100),LocalDateTime.now().plusSeconds(0),2,"机构"));

        }
    }


    @Test
    public void sortTrade(){
        System.out.println(JSON.toJSONString(trades,true));
        List<Trade> collect = trades.stream()
                .sorted(Comparator
                        //首先按照价格排序
                        .comparing(
                            Trade::getPrice,
                            //进行排序调整,将自然排序进行反转
                            Comparator.reverseOrder())
                        
                        //按照时间先后进行排序
                        .thenComparing(Trade::getTime)
                        
                        //按照交易量进行排序
                        .thenComparing(
                                Trade::getCount,
                                Comparator.reverseOrder())
                        
                        //自定义排序规则
                        .thenComparing(
                                //要排序的字段值
                                Trade::getType,
                                //排序规则
                                (type1, type2) -> {
                                    if ("机构".equals(type1) && "个人".equals(type2)) {
                                        return -1;
                                    } else if ("个人".equals(type1) && "机构".equals(type2)) {
                                        return 1;
                                    } else {
                                        return 0;
                                    }
                        })
                )
                .collect(Collectors.toList());


        System.out.println("排序后结果:");
        System.out.println(JSON.toJSONString(collect,true));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_子栖_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值