List集合自定义排序

SortBuilder类用于自定义List集合排序,支持多种排序方式,如nullsFirst、nullsLast、zerosFirst、zerosLast、自然排序等。通过提供方法如addAsc、addDesc和addCustom来设置排序规则,并通过sortList进行排序操作。示例中展示了如何根据属性对SeriesDiagramEntity列表进行排序。
public class SortBuilder<T> {

		// Never make these public
		static final int LEFT_IS_GREATER = 1;
		static final int RIGHT_IS_GREATER = -1;
		private static final Logger log = LoggerFactory.getLogger(SortBuilder.class);
		private List<SortFiled<T>> sortFileds = Lists.newLinkedList();
		private Map<String, Method> propertyMethodMap = null;
		private boolean nullsFirst;
		private boolean nullsLast;
		private boolean zerosFirst;
		private boolean zerosLast;
		private boolean natural;
		private Direction naturalDirection;

		private SortBuilder() {

		}

		public static <C> SortBuilder<C> newBuilder(Class clazz) {
			SortBuilder<C> sortBuilder = new SortBuilder<>();
			PropertyDescriptor[] propertyDescriptor = BeanUtils.getPropertyDescriptors(clazz);
			Map<String, Method> propertyMethodMap = new HashMap<>();
			for (PropertyDescriptor pd : propertyDescriptor) {
				String key = pd.getName();
				Method value = pd.getReadMethod();
				propertyMethodMap.put(key, value);
			}
			sortBuilder.propertyMethodMap = propertyMethodMap;
			return sortBuilder;
		}

		/**
		 * null 排序到最前面
		 */
		public SortBuilder<T> nullsFirst() {
			nullsFirst = true;
			nullsLast = false;
			return this;
		}

		/**
		 * null 排序到最后面
		 */
		public SortBuilder<T> nullsLast() {
			nullsFirst = false;
			nullsLast = true;
			return this;
		}

		/**
		 * 0 排序到最后面
		 */
		public SortBuilder<T> zerosLast() {
			zerosFirst = false;
			zerosLast = true;
			return this;
		}

		/**
		 * 0 排序到最前面
		 */
		public SortBuilder<T> zerosFirst() {
			zerosFirst = true;
			zerosLast = false;
			return this;
		}

		/**
		 * 自然排序 {1,5,3,2,4} = {1,2,3,4,5}
		 */
		public SortBuilder<T> natural() {
			natural = true;
			return this;
		}

		/**
		 * 自然排序 {1,5,3,2,4} = {1,2,3,4,5}
		 */
		public SortBuilder<T> natural(Direction direction) {
			natural = true;
			naturalDirection = direction;
			return this;
		}

		public SortBuilder<T> clear() {
			sortFileds.clear();
			return this;
		}

		/**
		 * 增加一个降序
		 *
		 * @param fieldName 属性
		 */
		public SortBuilder<T> addDesc(String fieldName) {
			addFieldMethod(fieldName, Direction.DESC);
			return this;
		}

		/**
		 * 增加一个自定义排序
		 *
		 * @param comparator 自定义比较器
		 */
		public SortBuilder<T> addCustom(Comparator<T> comparator) {
			sortFileds.add(SortFiled.builder(Direction.CUSTOM, null, comparator));
			return this;
		}


		/**
		 * 增加一个升序
		 *
		 * @param fieldName 属性
		 */
		public SortBuilder<T> addAsc(String fieldName) {
			addFieldMethod(fieldName, Direction.ASC);
			return this;
		}

		/**
		 * 增加一个字段排序模式
		 *
		 * @param fieldName 属性
		 * @param direction 排序方式
		 */
		private SortBuilder<T> addFieldMethod(String fieldName, Direction direction) {
			Method method = propertyMethodMap.get(fieldName);
			if (method == null) {
				log.error("NoSuchMethodException field:{}", fieldName);
			} else {
				sortFileds.add(SortFiled.<T>builder(direction, method, null));
			}
			return this;
		}

		public SortBuilder<T> sortList(List<T> list) {
			Collections.sort(list, buildComparator());
			return this;
		}

		private Comparator<T> buildComparator() {
			return new Comparator<T>() {
				public int compare(T o1, T o2) {
					int flag = 0;
					if (sortFileds.size() == 0 && natural) {
						flag = compareNatural(o1, o2, naturalDirection);
					} else {
						for (SortFiled<T> sortFiled : sortFileds) {
							Method method = sortFiled.getMethod();
							Direction direction = sortFiled.getDirection();
							if (direction == Direction.CUSTOM) {
								flag = sortFiled.getComparator().compare(o1, o2);
							} else {
								flag = this.compare(method, o1, o2, direction);
							}
							if (flag != 0) {
								break;
							}
						}
					}
					return flag;
				}

				private int compare(Method method, T left, T right, Direction direction) {
					int flag = 0;
					try {
						Object leftVal = method.invoke(left);
						Object rightVal = method.invoke(right);
						Class returnType = method.getReturnType();
						if (nullsFirst) {
							flag = compareNulls(returnType, leftVal, rightVal, false, direction);
						} else if (nullsLast) {
							flag = compareNulls(returnType, rightVal, leftVal, true, direction);
						} else {
							flag = compare(returnType, leftVal, rightVal, direction);
						}
					} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
						e.printStackTrace();
					}
					return flag;
				}

				private int compareNatural(Object leftVal, Object rightVal, Direction direction) {
					int flag;
					if (nullsFirst) {
						flag = compareNulls(leftVal, rightVal, false, direction);
					} else if (nullsLast) {
						flag = compareNulls(rightVal, leftVal, true, direction);
					} else {
						flag = compare(leftVal.getClass(), leftVal, rightVal, direction);
					}
					return flag;
				}

				private int compareNulls(Object leftVal, Object rightVal, boolean reverse, Direction direction) {
					return compareNulls(leftVal == null ? null : leftVal.getClass(), leftVal, rightVal, reverse, direction);
				}

				private int compareNulls(Class returnType, Object leftVal, Object rightVal, boolean reverse,
										 Direction direction) {
					if (leftVal == rightVal) {
						return 0;
					} else if (leftVal == null) {
						return RIGHT_IS_GREATER;
					} else if (rightVal == null) {
						return LEFT_IS_GREATER;
					} else {
						return reverse ? compare(returnType, rightVal, leftVal, direction) : compare(returnType, leftVal,
								rightVal, direction);
					}
				}

				private int compareZeros(BigDecimal leftNumber, BigDecimal rightNumber, boolean reverse, Direction direction) {
					if (leftNumber.compareTo(rightNumber) == 0) {
						return 0;
					} else if (leftNumber.compareTo(BigDecimal.valueOf(0)) == 0) {
						return RIGHT_IS_GREATER;
					} else if (rightNumber.compareTo(BigDecimal.valueOf(0)) == 0) {
						return LEFT_IS_GREATER;
					} else {
						return reverse ? compareNumber(rightNumber, leftNumber, direction) : compareNumber(leftNumber,
								rightNumber, direction);
					}
				}

				private int compareNumber(BigDecimal leftNumber, BigDecimal rightNumber, Direction direction) {
					if (leftNumber.compareTo(rightNumber) == 0) {
						return 0;
					} else {
						return direction == null || direction == Direction.ASC ? leftNumber.compareTo(rightNumber)
								: rightNumber.compareTo(leftNumber);
					}
				}

				private int compare(Class returnType, Object leftVal, Object rightVal, Direction direction) {
					int flag;
					if (Number.class.isAssignableFrom(returnType) || returnType == int.class || returnType == long.class
							|| returnType == double.class || returnType == float.class) {
						BigDecimal leftNumber = BigDecimal.valueOf(Double.valueOf(leftVal.toString()));
						BigDecimal rightNumber = BigDecimal.valueOf(Double.valueOf(rightVal.toString()));
						if (zerosFirst) {
							flag = compareZeros(leftNumber, rightNumber, false, direction);
						} else if (zerosLast) {
							flag = compareZeros(rightNumber, leftNumber, true, direction);
						} else {
							flag = compareNumber(leftNumber, rightNumber, direction);
						}
					} else {
						String methodReturn1 = leftVal.toString();
						String methodReturn2 = rightVal.toString();
						if (direction == null || direction == Direction.ASC) {
							flag = methodReturn1.compareTo(methodReturn2);
						} else {
							flag = methodReturn2.compareTo(methodReturn1);
						}
					}
					return flag;
				}
			};
		}

		/**
		 * 排序方式:
		 * <p/>
		 * ASC:升序,DESC:降序
		 */
		public enum Direction {
			ASC, DESC, CUSTOM
		}

		static class SortFiled<T> {
			private Method method;
			private Direction direction;
			private Comparator<T> comparator;


			SortFiled(Direction direction, Method method, Comparator<T> comparator) {
				this.method = method;
				this.direction = direction;
				this.comparator = comparator;
			}

			@SuppressWarnings("unchecked")
			public static <T> SortFiled<T> builder(Direction direction, Method method, Comparator<T> comparator) {
				return new SortFiled(direction, method, comparator);
			}

			public Method getMethod() {
				return method;
			}

			public void setMethod(Method method) {
				this.method = method;
			}

			public Direction getDirection() {
				return direction;
			}

			public void setDirection(Direction direction) {
				this.direction = direction;
			}

			public Comparator<T> getComparator() {
				return comparator;
			}

			public void setComparator(Comparator<T> comparator) {
				this.comparator = comparator;
			}
		}
	}

	使用方法:
	@Autowired
	private SeriesDiagramEntityService seriesDiagramEntityService;
	@org.junit.Test
	public void testSortBuilder() throws Exception{
		List<SeriesDiagramEntity> list = seriesDiagramEntityService.findAll(SeriesDiagramEntity.Fields.status.eq(CommonConstants.DataStatus.PUBLISH).limit(1000));
		SortBuilder.<SeriesDiagramEntity>newBuilder(SeriesDiagramEntity.class).addAsc("source").addAsc("displayOrder").addDesc("status").sortList(list);
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值