需求:最近项目需求中产品提到了列表需要支持拖动排序的问题,而当前系统中的列表是支持分页+条件搜索的,也就是说我们列表返回的orderNum肯定不是连续的。

动态效果如图:

20220427_112316

方案一

实现方案一: 不管数据向上还是向下移动,只会改变目标数据当前的位置和目标数据最后存放位置的之前的数据的orderNum值,其他数据的orderNum保持不变

  • 向上移动

  • 向下移动

代码实现


/*** 前端传递的body* @Author xiaosuhe* @Date 2022/4/11 11:05* @Version 1.0*/
@Data
public class MoveSortRequest {/*** 页码*/@ApiModelProperty("页码")private Integer pageNum;/*** 条数*/@ApiModelProperty("条数")private Integer pageSize;/*** 对象所属当前的 下标 索引位置*/@ApiModelProperty("对象所属当前的 下标 索引位置")private Integer startIndex;/*** 对象所属 拖拽后所属的 下标 索引的 位置*/@ApiModelProperty("对象所属 拖拽后所属的 下标 索引的 位置")private Integer endIndex;/***  targetId(拖拽的对象)*/@ApiModelProperty("targetId(拖拽的对象)")private Long targetId;/*** 名称搜索*/private String name;}

因为系统的列表是数据size是支持自己选择的,所以前端移动的数据要跟后端查询的数据对应上 ,所以需要前端传递pageSize和pageNum

排序代码如下:

 /*** @param allList    排序序 的集合(跟列表顺序保持一致,数据保存一直,也就是我们需要前端传递pageSize和pageNum的原因)* @param targetId   目标对象的Id(需要移动数据的ID)* @param startIndex 对象在列表的开始索引值[索引值从0 开始* @param endIndex   移动后的目标索引值[索引值从0 开始* @param isAsc      集合列表 是否正序 TRUE 正序* @Description: 构建 需要 排序的 list集合* @Return: java.util.List<T> 返回sort值变动的数据集合*/public static <T> List<T> getNeedUpdateSortList(List<T> allList, Long targetId, Integer startIndex, Integer endIndex, boolean isAsc) throws NoSuchFieldException, IllegalAccessException {List<T> buildList = new ArrayList<>();if (targetId == null || startIndex == null || endIndex == null) {throw new ServiceException(ErrorCodeEnum.PARAM_MISSING);}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;//不管上移还是下移,值改变目标当前位置和移动之后位置的orderNumif (flag) {//下移subList = allList.subList(Integer.parseInt(startIndex.toString()), Integer.parseInt(endIndex.toString()) + 1);} else {// 上移  subList左闭右开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((Long) (currentId))) {targetBean = bean;} else {//区间数据(不包含目标对象)excludeList.add(bean);}}if (targetBean == null) {throw new ServiceException(ErrorCodeEnum.CHECKTABLE_IS_NULL);}//===================   获取 排序区间 里面的 目标对象 + 排出目标对象之后的集合 end //============获取 拖拽对象  上移/下移 之后的 sort 值   //需要修改自己的排序值//需要 对索引区间的排序值(不包含排序对象自身) 进行 加1 或者 减 1T tempBean = null;if (flag) {//下移tempBean = excludeList.get(excludeList.size() - 1);} else {//上移动tempBean = excludeList.get(0);}Field sortField = tempBean.getClass().getDeclaredField("orderNum");sortField.setAccessible(true);Integer sort = (Integer) sortField.get(tempBean);//============获取 拖拽对象  上移/下移 之后的 sort 值   end========================//===================修改 目标对象  排序值  begin ==============Field targetBeanSortField = targetBean.getClass().getDeclaredField("orderNum");targetBeanSortField.setAccessible(true);//保存tagBean的orderNum值targetBeanSortField.set(targetBean, sort);//===================修改 目标对象  排序值  begin ==============//================修改  需要排序 区间(排序目标对象自身) 排序值  begin ========//处理for (T bean : excludeList) {sortField = bean.getClass().getDeclaredField("orderNum");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;}

细心的可以发现,方案一功能是能实现的,但是存在2个问题

  • 当在移动列表的时候,有人新增数据,那么展示的列表和调用移动排序回数据库查的数据就不会一一对应,导致潜在的移动排序失败。
  • 拖动排序的时候是支持条件搜索的,那说明我们列表展示的数据orderNum不是连续的数值,只是相对有序,我们对区间数据orderNum进行+1或者-1的时候可能导致数据表中的orderNum重复。

如图:经过筛选的数据移动出现orderNum重复的情况

一系列操作之后,清除筛选条件之后,发现orderNum经过上面的操作之后出现了多个orderNum重复的情况,所以对应orderNum不连续的,使用这种方式并不友好。

方案二

实现方案二、前端将移动前后列表的数据都给到后端,其实是一种数据平移的思想。

这种做法对排序的列表数据完全可靠,移动排序不会受到新增数据的影响,也解决了orderNum出现重复的问题

下面是代码实现,相对简单

请求body

@Data
public class MoveSortRequest {@ApiModelProperty("移动之前集合,需要传递orderNum")List<TableDTO> preMoveSortList;@ApiModelProperty("移动之后集合,不需要传递orderNum")List<TableDTO> afterMoveSortList;}@Data
public class TableDTO {private Long Id;private Integer orderNum;
}

逻辑处理之后批量更新

        List<TableDO> list = new ArrayList<>();List<TableDTO> afterMoveSortList = request.getAfterMoveSortList();List<TableDTO> preMoveSortList = request.getPreMoveSortList();if (CollectionUtils.isEmpty(afterMoveSortList )||CollectionUtils.isEmpty(preMoveSortList )){throw new ServiceException(ErrorCodeEnum.PARAM_MISSING);}for (int i = Constants.INDEX_ONE; i < afterMoveSortList .size(); i++) {TableDO tableDO = new TableDO();tableDO .setId(afterMoveSortList .get(i).getId());tableDO .setOrderNum(preMoveSortList .get(i).getOrderNum());list.add(tableDO);}return list;

总结

  • 方案一对于数据量比较大、排序准确度一般、容错较高的列表,
  • 方案一适合增删操作较少的列表
  • 方案二适合数据量一般,数据排序准确度较高,容错较低的列表
  • 方案二对操作列表不受限制

java实现列表拖动排序相关推荐

  1. java对列表数据排序_如何在Java中对列表进行排序

    java对列表数据排序 Sometimes we have to sort a list in Java before processing its elements. In this tutoria ...

  2. android 二级列表拖动排序_Excel的数据透视表六种排序方法

    Excel的数据透视表排序不像表格中那样操作灵活,很多小伙伴对此不熟悉,本文系统讲解数据透视表的各种排序. 一.常规排序 二.组内排序 三.多关键字排序 四.手动拖动排序 五.手动输入排序 六.设置透 ...

  3. 使用NetBeans Lambda支持在Java 8中使用Lambda表达式对列表进行排序

    作为JSR 335的一部分, Lambda表达式已从Java 8开始引入Java语言,这是Java语言的一个重大变化. 如果您想了解更多关于Lambda表达式以及JSR 335的信息,可以访问以下资源 ...

  4. java怎么从大到小排序元祖_在java中对元组列表进行排序的有效方法

    给定的通用数据类型看起来像这样:HashMap< EdgeTuple,Double> edgeList其中tuple是一个EdgeTuple类,Double是一个对任务不重要的权重: cl ...

  5. Vue - 列表拖曳排序 / 鼠标拖动改变顺序排列高效简洁组件(支持PC端与移动端触屏拖动,也可在滚动条内排序自动滚动,流畅丝滑无 BUG)

    前言 网上大部分教程代码臃肿且有BUG,另外代码注释没有很难读懂. 本文将从 0-1 完成列表拖曳排序功能(带动画),您只需要复制后改改样式即可, 支持电脑端与手机端兼容,代码干净整洁且超详细的注释. ...

  6. java list按字母排序_如何按字母顺序对列表进行排序?

    使用Collections.sort解决方案 如果您被迫使用该List,或者您的程序具有类似的结构 创建列表 添加一些国家名称 排序他们一次 永远不要再改变那个清单 然后Thilos的回答将是最好的方 ...

  7. java 元祖_在java中对元组列表进行排序的有效方法

    给定的通用数据类型看起来像这样:HashMap< EdgeTuple,Double> edgeList其中tuple是一个EdgeTuple类,Double是一个对任务不重要的权重: cl ...

  8. 【Android 事件分发】ItemTouchHelper 实现拖动排序

    Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...

  9. android程序设计排序方法,Android编程之可以实现拖动排序的listview控件

    DragSortListView是一个可以实现拖动排序的listview控件,是我看到的交互较为复杂的开源代码中不管是代码质量还是流畅性都最好的. DragSortListView 简称DSLV,继承 ...

  10. 联系人列表字母排序索引(三)

    也是忙忙碌碌好几天,今天又有时间了,继续这个文章的编写. 阅读这篇文章之前,请先阅读 联系人列表字母排序索引(一) 联系人列表字母排序索引(二) 今天是这篇文章的最后一部分,主要内容包括以下几点: 1 ...

最新文章

  1. 奇葩错误:不同变量名称相同
  2. python里面的之前打过的记忆信息-python中的记忆:如何缓存函数的运行结果(1)
  3. delphi XE 下打开内存泄漏调试功能
  4. html和html5学习
  5. Python Numpy学习手册(翻译自斯坦福大学 CS231n: Convolutional Neural Networks for Visual Recognition)
  6. Spring Batch 专题
  7. JZOJ 5939. 【NOIP2018模拟10.30】阻击计划
  8. RegEnumValue枚举注册表值小记
  9. 部署zookeeper分布式节点
  10. Logback介绍及入门
  11. flutter实现Icon可以用Image替换
  12. WOW、ScrollReveal:WOW.js和ScrollReveal.js基础学习
  13. C1WebChart 图形化处理。
  14. 【项目实战】基于 springboot + mybatis + mysql 的电脑商城项目(附源码)
  15. 8.1.CentOS7安装Spark安装部署及standalone模式介绍
  16. 分析图片相似度的软件,图片相似度比对算法
  17. java pfx 和cer_pfx证书和CER证书
  18. Validation and Data leakages
  19. NS2 实现有 20 个节点的 WLAN
  20. Sybase ASE 修改登陆用户密码

热门文章

  1. C++实现24点游戏
  2. DHTMLXGantt and DHTMLXGantt pro
  3. pdftomusic pro(音乐谱曲软件) v1.0.4
  4. 小程序毕设作品之微信企业公司小程序毕业设计(4)开题报告
  5. 【验证小白】只有SV+modelsim学验证(3)——加checker到环境中
  6. 聚类算法-k均值聚类(K-means)
  7. vue生成静态html文件_Vue项目打包成一个HTML文件(包含CSS,JS)
  8. RTK差分通讯链路---电台
  9. cholesky分解java代码_cholesky分解的实现
  10. 8086CPU标志位