在项目中经常能遇到,需要对某些数据集合进行多维度排序的需求。对于集合多条件排序解决方案也有很多,今天我们就介绍一种,思路大致是设置一个分值的集合,这个分值是按照需求来设定大小的,再根据分值的大小对集合排序。
- package com.user;
- import lombok.AllArgsConstructor;
- import lombok.Builder;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * @Author toutou
- * @Date 2023/2/18
- * @Des
- */
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- @Builder
- public class User {
- private Integer id;
- /**
- * 等级
- */
- private int grade;
- /**
- * 所在省份id
- */
- private int provinceId;
- /**
- * 所在城市ID
- */
- private int cityId;
- /**
- * 是否是活跃用户,true活跃,false不活跃
- */
- private boolean lively;
- /**
- * 是否开通支付,true开通,false未开通
- */
- private boolean pay;
- public static List<User> getTestUserList() {
- List<User> list = new ArrayList<>();
- list.add(User.builder().id(0).grade(1).provinceId(1).cityId(22).lively(false).pay(false).build());
- list.add(User.builder().id(1).grade(1).provinceId(1).cityId(100).lively(true).pay(true).build());
- list.add(User.builder().id(2).grade(3).provinceId(5).cityId(100).lively(true).pay(true).build());
- list.add(User.builder().id(3).grade(2).provinceId(1).cityId(98).lively(true).pay(true).build());
- list.add(User.builder().id(4).grade(2).provinceId(1).cityId(100).lively(true).pay(true).build());
- list.add(User.builder().id(5).grade(2).provinceId(3).cityId(100).lively(true).pay(true).build());
- list.add(User.builder().id(6).grade(2).provinceId(1).cityId(101).lively(true).pay(false).build());
- list.add(User.builder().id(7).grade(1).provinceId(6).cityId(100).lively(false).pay(true).build());
- list.add(User.builder().id(8).grade(1).provinceId(1).cityId(98).lively(true).pay(false).build());
- list.add(User.builder().id(9).grade(1).provinceId(5).cityId(100).lively(true).pay(true).build());
- return list;
- }
- }
- package com.util;
- import java.math.BigDecimal;
- import java.util.List;
- /**
- * @Author toutou
- * @Date 2023/2/18
- * @Des
- */
- public class SortHelper {
- /**
- * 比较两个BigDecimal集合
- * @param left
- * @param right
- * @return leftList<rightList返回-1;leftList=rightList返回0;leftList>rightList返回1;
- */
- public static int compareBigDecimalList(List<BigDecimal> left, List<BigDecimal> right) {
- int length = Math.max(left.size(), right.size());
- for (int i = 0; i < length; i++) {
- if (left.size() < i + 1) {
- return -1;
- }
- if (right.size() < i + 1) {
- return 1;
- }
- int value = left.get(i).compareTo(right.get(i));
- if (value != 0) {
- return value;
- }
- }
- return 0;
- }
- }
- package com.util;
- import com.user.User;
- import org.apache.commons.lang3.tuple.ImmutablePair;
- import java.math.BigDecimal;
- import java.util.ArrayList;
- import java.util.Comparator;
- import java.util.List;
- import java.util.stream.Collectors;
- import reactor.core.publisher.Flux;
- /**
- * @Author toutou
- * @Date 2023/2/18
- * @Des
- */
- public class Sort {
- /**
- * 当前用户所在城市id,所在省份id
- * @param cityId
- * @param provinceId
- * @return
- */
- public List<User> sortUserList(int cityId, int provinceId) {
- // 获取初始化测试list数据
- List<User> list = User.getTestUserList();
- if(list == null || list.size() == 0){
- return list;
- }
- List<ImmutablePair<User, List<BigDecimal>>> userAndScore = new ArrayList<>();
- for (User user : list){
- // 初始化一个排序的分值list
- List<BigDecimal> scoreList = Flux.range(0, 6).map(p -> BigDecimal.ZERO).collectList().block();
- userAndScore.add(new ImmutablePair<>(user, scoreList));
- if(user.isPay()){
- // 付费用户排序,付费用户为1,非付费用户为2
- scoreList.set(0, BigDecimal.valueOf(1));
- if(user.getCityId() == cityId){
- scoreList.set(1, BigDecimal.valueOf(1));
- }else{
- scoreList.set(1, BigDecimal.valueOf(2));
- }
- if(user.getProvinceId() == provinceId){
- scoreList.set(2, BigDecimal.valueOf(1));
- }else{
- scoreList.set(2, BigDecimal.valueOf(2));
- }
- scoreList.set(3, BigDecimal.valueOf(-user.getGrade()));
- if(user.isLively()){
- scoreList.set(4, BigDecimal.valueOf(1));
- }else{
- scoreList.set(4, BigDecimal.valueOf(2));
- }
- scoreList.set(5, BigDecimal.valueOf(-user.getId()));
- }else{
- scoreList.set(0, BigDecimal.valueOf(2));
- scoreList.set(1, BigDecimal.valueOf(-user.getGrade()));
- if(user.getCityId() == cityId){
- scoreList.set(2, BigDecimal.valueOf(1));
- }else{
- scoreList.set(2, BigDecimal.valueOf(2));
- }
- scoreList.set(3, BigDecimal.valueOf(-user.getId()));
- }
- }
- return userAndScore.stream().sorted(Comparator.comparing(p -> p.getValue(), SortHelper::compareBigDecimalList)).map(ImmutablePair::getLeft).collect(Collectors.toList());
- }
- }