Java 分类上移/下移/拖拽排序工具类

前言:业务上经常会有 对分类/菜单 等列表进行拖拽排序 上移/下移等操作,同时后台也需要对整个列表的sort值进行后台更新和前台保持一致
前端需要传被拖拽的对象的id,开始/结束后的下标索引[下标从0开始],同时要求数据字段中包含(long)id,(Integer)sort基础字段,最终返回sort值需要更新的集合,同步更新数据库
package com.example.bean;


import lombok.Data;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;


/**
 * @author 徐刘
 * @version 1.0
 * @desc demo
 * @date 2021/6/25 13:46
 */

public class Test2 {
    @Data
    static class Test1 {
        private Integer id;
        private Integer sort;
        private String name;
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

        List<Test1> list = new ArrayList<>();

        // 组装一个 list 集合数据 正序展示 sort值 从小到大[0-->4]
        /**
         * [
         *   {id:0,sort:0,name:name0}, 下标索引 0
         *   {id:1,sort:1,name:name1},        1
         *   {id:2,sort:2,name:name2},        2
         *   {id:3,sort:3,name:name3},        3
         *   {id:4,sort:4,name:name4}         4
         * ]
         *
         */
        for (int i = 0; i < 5; i++) {
            Test1 test1 = new Test1();
            test1.setId(i);
            test1.setSort(i);
            test1.setName("name" + i);
            list.add(test1);
        }
        // targetId(拖拽的对象) 即 对应的是 {id:1,sort:1,name:name1} 数据
        Integer targetId = 1;
        // 对象所属当前的 下标 索引位置  1
        Integer startIndex = 1;
        // 对象所属 拖拽后所属的 下标 索引的 位置[例:把name1 拖拽到  name3 之后的位置 拖拽后的name1的下标索引 即为3]
        Integer endIndex = 3;
        //list是按照sort 值升序查询 的还是降序查询的
        boolean isAsc = true;
        //返回sort 值有变化需要更新的集合
        List<Test1> needUpdateSortList = getNeedUpdateSortList(list, targetId, startIndex, endIndex, isAsc);
        for (Test1 bean : needUpdateSortList) {
            System.out.println(bean);
        }
        //输出的结果 即 name1 在 在name3 之后 同时 name1 的sort 值从 1-->3 ;name2,name3 的排序值进行了-1
        //Test2.Test1(id=2, sort=1, name=name2)
        //Test2.Test1(id=3, sort=2, name=name3)
        //Test2.Test1(id=1, sort=3, name=name1)

    }

    /**
     * @param allList    排序序 的集合(跟列表顺序保持一致)
     * @param targetId   目标对象的Id
     * @param startIndex 对象在列表的开始索引值[索引值从0 开始]
     * @param endIndex   移动后的目标索引值[索引值从0 开始]
     * @param isAsc      集合列表 是否正序 TRUE 正序
     * @Description: 构建 需要 排序的 list集合
     * @Author: 徐刘
     * @Date: 2021/6/29 11:49
     * @Return: java.util.List<T> 返回sort值变动的数据集合
     */
    public static <T> List<T> getNeedUpdateSortList(List<T> allList, Integer targetId, Integer startIndex, Integer endIndex, boolean isAsc) throws NoSuchFieldException, IllegalAccessException {
        List<T> buildList = new ArrayList<>();
        if (targetId == null || startIndex == null || endIndex == null) {
            throw new IllegalAccessException("targetId/startIndex/endIndex不能为空!");
        }
        if (CollectionUtils.isEmpty(allList) || startIndex.equals(endIndex)) {
            return buildList;
        }
        //需要 修改排序值得 数据集合 不包含 目标对象 本身
        List<T> excludeList = new ArrayList();
        //目标 对象
        T targetBean = null;
        //截取的 开始 索引  和 结束 索引 之间的 list 包含 targetBean(拖拽排序目标自身) 的一个 集合
        List<T> subList = null;

        //需改排序规则 (只修改 索引区间的值)
        //== ================获取 索引区间的 数据集合   begin ==================
        boolean flag = endIndex > startIndex;
        if (flag) {
            //下移
            subList = allList.subList(Integer.parseInt(startIndex.toString()), Integer.parseInt(endIndex.toString()) + 1);
        } else {
            // 上移
            subList = allList.subList(Integer.parseInt(endIndex.toString()), Integer.parseInt(startIndex.toString()) + 1);
        }
        //== ================获取 索引区间的 数据集合   end  ==================

        if (CollectionUtils.isEmpty(subList)) {
            return buildList;
        }

        //===================   获取 排序区间 里面的 目标对象 + 排出目标对象之后的集合 begin =============
        for (T bean : subList) {
            Field idField = bean.getClass().getDeclaredField("id");
            idField.setAccessible(true);
            Object currentId = idField.get(bean);
            if (targetId.equals((Integer) (currentId))) {
                targetBean = bean;
            } else {
                excludeList.add(bean);
            }
        }
        if (targetBean == null) {
            throw new IllegalAccessException("目标对象不存在!");
        }
        //===================   获取 排序区间 里面的 目标对象 + 排出目标对象之后的集合 end  =============

        //============获取 拖拽对象  上移/下移 之后的 sort 值   begin========================
        //需要修改自己的排序值
        //需要 对索引区间的排序值(不包含排序对象自身) 进行 加1 或者 减 1
        T tempBean = null;
        if (flag) {
            //下移
            tempBean = excludeList.get(excludeList.size() - 1);
        } else {
            //上移动
            tempBean = excludeList.get(0);
        }
        Field sortField = tempBean.getClass().getDeclaredField("sort");
        sortField.setAccessible(true);
        Integer sort = (Integer) sortField.get(tempBean);
        //============获取 拖拽对象  上移/下移 之后的 sort 值   end========================

        //===================修改 目标对象  排序值  begin ==============
        Field targetBeanSortField = targetBean.getClass().getDeclaredField("sort");
        targetBeanSortField.setAccessible(true);
        targetBeanSortField.set(targetBean, sort);
        //===================修改 目标对象  排序值  begin ==============

        //================修改  需要排序 区间(排序目标对象自身) 排序值  begin ========
        //处理
        for (T bean : excludeList) {
            sortField = bean.getClass().getDeclaredField("sort");
            sortField.setAccessible(true);
            sort = (Integer) sortField.get(bean);
            //flag true : 下移 非拖动对象 自身 排序索引值 需要 -1; false 反之
            if (isAsc) {
                //正序
                sortField.set(bean, flag ? (sort - 1) : (sort + 1));
            } else {
                //倒叙
                sortField.set(bean, flag ? (sort + 1) : (sort - 1));
            }
        }
        //================修改  需要排序 区间(排序目标对象自身) 排序值  end  ========

        buildList.addAll(excludeList);
        buildList.add(targetBean);
        return buildList;
    }


}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值