通过Stream对List进行分页、动态排序

1 篇文章 0 订阅
1 篇文章 0 订阅

通过Stream对List进行分页、动态排序

开发时有些场景需要对数据进行分页或根据某个字段排序,通常在数据库中即可完成,但是往往业务需求会在数据库中查询出来以后做一些更多的业务操作,无法直接通过数据库分页、排序,可以通过Stream流对集合进行分页、动态排序。

用到的Maven依赖

        <!--        lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.21</version>
        </dependency>

ListUtil代码

package com.example;

import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.comparator.Comparators;

import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ListUtil {

    /**
     * 给List进行排序、分页
     * @param dataList 数据集合
     * @param clazz 集合数据类型
     * @param asc 是否正序
     * @param pageNum 当前页
     * @param pageSize  每页数量
     * @param orderByColumn 排序字段
     * @return  集合
     * @param <T> 集合数据类型
     */
    public static <T> List<T> page(List<T> dataList, Class<T> clazz, boolean asc, Long pageNum, Long pageSize, String orderByColumn) {

        //空集合直接返回原List
        if (CollectionUtils.isEmpty(dataList)) {
            return dataList;
        }

        //根据排序字段、是否正序排序
        if (StringUtils.hasText(orderByColumn)) {
            dataList.sort(comparable(clazz, orderByColumn, asc));
        }
        //分页参数确实直接返回原List
        if (Objects.isNull(pageNum) || Objects.isNull(pageSize)) {
            return dataList;
        }
        //对排序完的集合进行分页
        return dataList.stream().skip(pageSize * (pageNum - 1)).limit(pageSize).collect(Collectors.toList());
    }

    /**
     * 对List进行排序
     * @param dataList 数据集合
     * @param clazz 集合数据类型
     * @param asc 是否正序
     * @param orderByColumn 排序字段
     * @return  集合
     * @param <T> 集合数据类型
     */
    public static <T> List<T> page(List<T> dataList, Class<T> clazz, boolean asc, String orderByColumn) {
        return page(dataList, clazz, asc, null, null, orderByColumn);
    }

    /**
     * 排序
     * @param clazz 类型
     * @param orderByColumn 排序字段
     * @param isAsc 是否正序
     * @return 排序
     * @param <T> 类型
     */
    private static <T> Comparator<? super T> comparable(Class<T> clazz, String orderByColumn, boolean isAsc) {
        Method getterMethod = BeanUtils.findGetterMethod(clazz, orderByColumn);
        Comparator<T> tComparator = (c1, c2) -> {
            try {
                Object c1v = getterMethod.invoke(c1);
                Object c2v = getterMethod.invoke(c2);
                return Comparators.comparable().compare(Optional.ofNullable(c1v).orElse(""), Optional.ofNullable(c2v).orElse(""));
            } catch (Exception e) {
                e.printStackTrace();
                //TODO 这里可以做一些报错的提醒
            }
            return 0;
        };

        return isAsc ? tComparator : tComparator.reversed();

    }

    //过滤
    public static <T> List<T> filter(List<T> dataList, Predicate<T> predicate) {
        return dataList.stream().filter(predicate).collect(Collectors.toList());
    }

	/**
	* 通过反射获取getter
	*
	*/
	@SneakyThrows
    public static <T> Method findGetterMethod(Class<T> clazz, String fieldName) {
        String getterName = "get" + capitalizeFirstLetter(fieldName);
        return clazz.getMethod(getterName);
    }

    /**
     * 首字母大写
     * @param s
     * @return
     */
    public static String capitalizeFirstLetter(String s) {
        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }


}

测试

public static class User {

        private Long id;
        private String userName;

        public User(Long id, String userName) {
            this.id = id;
            this.userName = userName;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", userName='" + userName + '\'' +
                    '}';
        }
    }
测试代码
	@Test
    public void test() {
        ArrayList<User> users = new ArrayList<User>();
        users.add(new User(1L, "zhangsan"));
        users.add(new User(2L, "lisi"));
        users.add(new User(3L, "wangwu"));
        users.add(new User(4L, "zhaoliu"));

        List<User> pageList = ListUtil.page(users, User.class, false, 1L, 2L, "id");
        System.out.println("pageList = " + pageList);
    }
结果
pageList = [User{id=4, userName='zhaoliu'}, User{id=3, userName='wangwu'}]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用stream进行分页排序。首先,使用skip()方法跳过前面的元素,以确定要显示的页数和页面大小。然后,使用limit()方法限制结果集的大小。接下来,使用sort()方法对结果进行排序。例如,可以使用Comparator.comparing()方法传入要排序的属性和排序顺序,再使用reversed()方法进行降序排序。最后,将结果集收集到一个列表中。以下是一个示例代码: list.stream() .sorted(Comparator.comparing(Project::getId).reversed()) .skip((pageNo - 1) * pageSize) .limit(pageSize) .collect(Collectors.toList()); 在上述示例中,我们首先对列表进行排序,按照项目的id属性进行降序排序。然后,使用skip()方法跳过前面的元素,以确定要显示的页数和页面大小。最后,使用limit()方法限制结果集的大小,并将结果集收集到一个列表中。这样就可以实现stream流的分页排序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [stream分页+排序Java实际开发中list.sort()集合排序详解之多条件排序分页、空值null的最常用解决方案...](https://blog.csdn.net/weixin_46460843/article/details/120416965)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值