java简要实现优先级的分组排序

写在前面

本排序适用于内存排序,并且有强制的优先级;比如 有秒杀活动的 > 加入购物车 > 运营元素 > 店铺评分 > 历史购买 > 普通活动;本功能用户实际项目中搜索的展现以及推荐(当然优先级没有上面列的那么简单);该版本性能还可以继续提供,因为时间有限,所以先出一个版本

原文章链接

代码示例

  • 排序元素准备:
    bean包下:
    OrderData(主要放置待排序的id和排序因子所对应的值)
package littlehow.sort.group.bean;


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * OrderData
 *
 * @author littlehow
 * @time 2017-08-14 11:23
 */
public class OrderData<T> {
    private T id;

    /**
     *  得分
     */
    private Map<String, Comparable> orderScoreMap;

    /**
     * 属性
     */
    private Map<String, Object> attribute;

    public void add(String key, Comparable value) {
        if (orderScoreMap == null) orderScoreMap = new HashMap<>();
        orderScoreMap.put(key, value);
    }

    public Comparable get(String key) {
        if (orderScoreMap == null) return null;
        return orderScoreMap.get(key);
    }

    public Map<String, Comparable> getOrderScoreMap() {
        return orderScoreMap;
    }

    public void setAttribute(String key, Object value) {
        if (attribute == null) attribute = new HashMap<>();
        attribute.put(key, value);
    }

    public Object getAttribute(String key) {
        if (attribute == null) return null;
        return attribute.get(key);
    }

    /**
     * 兼容前期已经调用的版本
     * @param map
     */
    @Deprecated
    public void setOrderScoreMap(Map<String, Double> map) {
        Set<Map.Entry<String, Double>> entrySet = map.entrySet();
        for (Map.Entry<String, Double> entry : entrySet) {
            add(entry.getKey(), entry.getValue());
        }
    }

    public T getId() {
        return id;
    }

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

    public boolean equalsProperty(OrderData<T> other, String key) {
        if (other == null) return false;
        return this.get(key).equals(other.get(key));
    }
}
  • OrderDirect 主要指明排序方向
package littlehow.sort.group.bean;

/**
 * OrderDirect 排序方向
 *
 * @author littlehow
 * @time 2017-08-14 11:10
 */
public enum OrderDirect {
    DESC(-1),//倒序
    ASC(1)//正序
    ;
    public final int v;
    OrderDirect(int v) {
        this.v = v;
    }
}

package littlehow.sort.group.bean;  
/**  
 * OrderProperty 排序要素    
 * @author littlehow  
 * @time 2017-08-14 11:11  
 */ 

public class OrderProperty implements Comparable<OrderProperty> { 
    /**  * 要素标识  */  
    private String id;   
    /**  * 要素序号  */  
    private int ordinal;   
    /**  * 要素排序方向  */  
    private OrderDirect orderDirect;   
    /**  * 是否为是非因子  */  
    private boolean trueOrFalse;   
    /**  * 为null的时候的默认值  */  
    private Comparable defaultNullValue = 0.0;   
    public OrderProperty() { } 
    public OrderProperty(String id, int ordinal) { 
        this(id, ordinal, OrderDirect.DESC);
    } 
    public OrderProperty(String id, Integer ordinal, OrderDirect orderDirect) {
        this.id = id;  
        this.ordinal = ordinal;  
        this.orderDirect = orderDirect;  
   } 

    public OrderProperty(String id, int ordinal, OrderDirect orderDirect, boolean trueOrFalse) { 
        this(id, ordinal, orderDirect);  
        this.trueOrFalse = trueOrFalse;  
    } 

    public OrderProperty(String id, int ordinal, OrderDirect orderDirect, boolean trueOrFalse, Comparable defaultNullValue) { 
        this(id, ordinal, orderDirect, trueOrFalse);  
        this.defaultNullValue = defaultNullValue;  
    } 

    public String getId() { 
        return id;  
    } 
   
    public void setId(String id) { 
        this.id = id;  
    } 

    public int getOrdinal() { 
        return ordinal;  
    } 

   public void setOrdinal(int ordinal) { 
       this.ordinal = ordinal;  
   } 

   public OrderDirect getOrderDirect() { 
       return orderDirect;  
   } 
   public void setOrderDirect(OrderDirect orderDirect) { 
       this.orderDirect = orderDirect;  
   } 
   public boolean isTrueOrFalse() { 
       return trueOrFalse;  
   } 

   public void setTrueOrFalse(boolean trueOrFalse) { 
       this.trueOrFalse = trueOrFalse;  
   } 
  
   public Comparable getDefaultNullValue() { 
       return defaultNullValue;  
   } 
   
   public void setDefaultNullValue(Comparable defaultNullValue) {
       this.defaultNullValue = defaultNullValue;  
   } 
   
   /**  
    * 正序排列 ASC  
    * @param other  
    * @return  
    */  
    public int compareTo(OrderProperty other) { 
        return this.ordinal > other.ordinal ? 1 : this.ordinal == other.ordinal ? 0 : -1;  
    } 

  @Override  
  public String toString() { 
      return "{id=" + id + ", ordinal=" + ordinal + ", orderDirect=" + orderDirect + "}";  
  }
} 


package littlehow.sort.group.bean;

import java.util.Comparator;
import java.util.List;

/**
 * OrderDataComparator
 *
 * @author littlehow
 * @time 2017-08-15 15:50
 */
public class OrderDataComparator implements Comparator<OrderData> {
    private List<OrderProperty> orderProperties;
    public OrderDataCompara

tor(List<OrderProperty> orderProperties) {
        this.orderProperties = orderProperties;
    }

    /**
     * 进行排序
     * @param o1
     * @param o2
     * @return
     */
    public int compare(OrderData o1, OrderData o2) {
        for (OrderProperty orderProperty : orderProperties) {
            //排序key
            String key = orderProperty.getId();
            //排序默认值
            Comparable dv = orderProperty.getDefaultNullValue();
            //排序方向
            OrderDirect orderDirect = orderProperty.getOrderDirect();
            //元素一对应排序因子
            Comparable c1 = o1.get(key);
            if (c1 == null) c1 = dv;
            //元素二对应排序因子
            Comparable c2 = o2.get(key);
            if (c2 == null) c2 = dv;

            if (c1.compareTo(c2) == 0) {
                continue;//如果是一样的,则进行下一排序因子的比较
            }
            return c1.compareTo(c2) * orderDirect.v;
        }
        //如果抵达这一步,证明前面要素比较全部一致,不需要进行元素交换
        return 0;
    }
}
  • 工具包
package littlehow.sort.group.utils;   
import littlehow.sort.group.bean.OrderData; 
import littlehow.sort.group.bean.OrderDataComparator; 
import littlehow.sort.group.bean.OrderProperty;  
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List;  
/**  
* SortUtil  *  
* @author littlehow  
* @time 2017-08-14 11:42  
*/ 
public abstract class SortUtils { 
	/**  
	* 进行实际排序  
	* @param orderDatas  
	* @param orderProperties  
	* @param max  
	*/  
	public static <T> void order(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties, int max) { 
	//将要素要优先级排序, 优先级高的排在前面  
	Collections.sort(orderProperties);  
	sort(orderDatas, new OrderDataComparator(orderProperties), max);  
} 

/**  
 *  
 * @param list  
 * @param comparator  
 * @param maxSize  
 */  
 public static <T> void sort(List<OrderData<T>> list, Comparator<OrderData> comparator, int maxSize) { 
     int length = list.size();  
     if (maxSize > length) maxSize = length;  
     bubble(list, (Comparator) comparator, maxSize);  
 } 

 /**  
  * 支持局部排序  
  * @param targets  
  * @param comparator  
  * @param maxSize -- 想要排序的数量  
  */  
  private static <T> void bubble(List<OrderData<T>> targets, Comparator comparator, int maxSize) { 
      int length = targets.size();  
      for (int i = 0; i < maxSize; i++) { 
          for (int j = i + 1; j < length; j++) { 
             if (comparator.compare(targets.get(i), targets.get(j)) > 0) {
                 //进行元素置换  
                 swap(targets, i, j);  
             } 
         } 
     } 
 } 

 /**  
  * 元素交换  
  * @param targets  
  * @param i  
  * @param j  
  * @param <T>  
  */  
  private static <T> void swap(List<OrderData<T>> targets, int i, int j) { 
      OrderData<T> tmp = targets.get(i);  
      targets.set(i, targets.get(j));  
      targets.set(j, tmp);  
  } 
} 

  • 其他类
package com.kom.base.sort.utils;


import java.lang.reflect.Field;
import java.util.*;

/**
 * CollectionUtils
 *
 * @author littlehow
 * @time 2017-06-09 10:07
 */
public class CollectionUtils {

    private static final List EMPTY_LIST = new ArrayList();
    //私有构造,也可把类提取成抽象类
    private CollectionUtils(){}

    /**
     * 判断集合是否为空
     * @param collection
     * @return
     */
    public static boolean isEmpty(Collection collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合非空
     * @param collection
     * @return
     */
    public static boolean isNotEmpty(Collection collection) {
        return !isEmpty(collection);
    }


    /**
     * 截取list
     * @param orig
     * @param startIndex
     * @param <T>
     * @return
     */
    public static <T> List<T> subList(List<T> orig, int startIndex) {
        if (isEmpty(orig) || startIndex >= orig.size()) {
            return EMPTY_LIST;
        }
        if (startIndex == 0) return orig;
        return subList(orig, startIndex, orig.size());
    }

    /**
     * 截取list集合 前闭后开区间, 如果起始位置为0,终止位置和集合总条数一致,则直接返回原有集合
     * @param orig        -- 要截取的集合
     * @param startIndex  -- 起始下标
     * @param endIndex    -- 终止下标但不包含该值
     * @param <T>
     * @return
     */
    public static <T> List<T> subList(List<T> orig, int startIndex, int endIndex) {
        if (isEmpty(orig) || startIndex >= endIndex || startIndex >= orig.size() || endIndex > orig.size()) {
            return EMPTY_LIST;
        }
        //如果起始位置为0,终止位置和集合总条数一致,则直接返回原有集合
        if (orig.size() == endIndex && startIndex == 0) return orig;
        List<T> desc = new ArrayList<T>(endIndex - startIndex);
        for (int i = startIndex; i < endIndex; i++) {
            desc.add(orig.get(i));
        }
        return desc;
    }
}

package littlehow.sort.group.service;


import littlehow.sort.group.bean.OrderData;
import littlehow.sort.group.bean.OrderProperty;

import java.util.ArrayList;
import java.util.List;

/**
 * SortService
 *
 * @author littlehow
 * @time 2017-08-16 13:58
 */
public abstract class SortService {
    /**
     * 全体排序
     * @param orderDatas
     * @param orderProperties
     * @param <T>
     * @return
     */
    public abstract  <T> List<T> sort(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties);

    /**
     * 按照top max 排序
     * @param orderDatas
     * @param orderProperties
     * @param maxSize
     * @param <T>
     * @return
     */
    public abstract  <T> List<T> sortMax(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties, int maxSize);

    /**
     * 分页排序
     * @param orderDatas
     * @param orderProperties
     * @param pageNo
     * @param pageSize
     * @param <T>
     * @return
     */
    public abstract <T> List<T> sortPaging(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties, int pageNo, int pageSize);

    /**
     * 获取id
     * @param orderDatas
     * @param start
     * @param end
     * @return
     */
    public final <T> List<T> getIds(List<OrderData<T>> orderDatas, int start, int end) {
        List<T> ids = new ArrayList<>(orderDatas.size());
        for (int i = start; i < end; i++) {
            ids.add(orderDatas.get(i).getId());
        }
        return ids;
    }
}

package littlehow.sort.group.service;


import littlehow.sort.group.bean.OrderData;
import littlehow.sort.group.bean.OrderProperty;
import littlehow.sort.group.utils.CollectionUtils;
import littlehow.sort.group.utils.SortUtils;

import java.util.List;

/**
 * SortService
 *
 * @author littlehow
 * @time 2017-08-16 12:24
 */
public class GroupSortService extends SortService{
    @Override
    public <T> List<T> sort(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties) {
        if (CollectionUtils.isEmpty(orderDatas)) return null;
        return sortMax(orderDatas, orderProperties, orderDatas.size());
    }


    @Override
    public <T> List<T> sortMax(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties, int maxSize) {
        if (CollectionUtils.isEmpty(orderDatas) || CollectionUtils.isEmpty(orderProperties)) return null;
        if (orderDatas.size() == 1) {//只有一个元素就没有排序的必要
            return getIds(orderDatas, 0, 1);
        }
        if (maxSize > orderDatas.size()) {
            maxSize = orderDatas.size();
        }
        //进行排序
        SortUtils.order(orderDatas, orderProperties, maxSize);
        return getIds(orderDatas, 0, maxSize);
    }

    @Override
    public <T> List<T> sortPaging(List<OrderData<T>> orderDatas, List<OrderProperty> orderProperties, int pageNo, int pageSize) {
        if (CollectionUtils.isEmpty(orderDatas) || CollectionUtils.isEmpty(orderProperties)) return null;
        int start = (pageNo - 1) * pageSize;
        int end = start + pageSize;
        //分页已经超出范围
        if (start >= orderDatas.size()) return null;
        if (end > orderDatas.size()) {
            end = orderDatas.size();
        }
        //进行排序
        SortUtils.order(orderDatas, orderProperties, end);
        return getIds(orderDatas, start, end);
    }
}
  • 简单测试用例TestSort
package littlehow.sort.group.test;

import littlehow.sort.group.bean.OrderData;
import littlehow.sort.group.bean.OrderDirect;
import littlehow.sort.group.bean.OrderProperty;
import littlehow.sort.group.service.GroupSortService;
import littlehow.sort.group.service.SortService;

import java.util.*;

/**
 * TestSort
 *
 * @author littlehow
 * @time 2017-08-14 17:08
 */
public class TestSort {

    static double[] orderScore = {1.5, 1.8, 2.9, 3.3, 1.5, 1.6, 3.1, 2.9,0,1,2,1.6,0,1.5, 0.7, 0,7, 1.5, 1.5, 3.3, 1.6, 4.2,1,1,1.5, 4.1,1.5,1.6};
    static double[] trueFalse = {0.0, 1.0};
    static Random random = new Random();
    static int length = orderScore.length;
    static SortService sortService = new GroupSortService();

    private static List<OrderProperty> orderProperties = new ArrayList<OrderProperty>();
    static {
        orderProperties.add(new OrderProperty("seckill", 1, OrderDirect.DESC, true));
        orderProperties.add(new OrderProperty("cart", 2, OrderDirect.ASC, true));
        orderProperties.add(new OrderProperty("marketingText", 3, OrderDirect.ASC));
        orderProperties.add(new OrderProperty("shopScore", 4, OrderDirect.DESC));
        orderProperties.add(new OrderProperty("historyPurchase", 5, OrderDirect.ASC));
        orderProperties.add(new OrderProperty("activity", 6, OrderDirect.ASC));
    }
    public static void main(String[] args) {
        test();
    }

    static void test() {
        List<OrderData<Integer>> orderDatas = new ArrayList<>();
        for (int i=1; i<11; i++) {
            orderDatas.add(getOrderData(i));
        }
        for (OrderData orderData : orderDatas) {
            System.out.println(orderData.getId() + ":" + orderData.getOrderScoreMap());
        }
//        System.out.println("========================分割===============================");
        long start = System.currentTimeMillis();
        for (int i=0;i<1;i++) {
           
            Collections.shuffle(orderDatas); 
            for (OrderData orderData : orderDatas) { 
               System.out.print(orderIntData.getId()+"-"); 
            }
      List<Integer> result = sortService.sortPaging(orderDatas, orderProperties, 1, 10); 
      System.out.println(result); 
   } 
   System.out.println("-------------------->耗时:" + (System.currentTimeMillis() - start) + "毫秒"); 
} 
static OrderData getOrderData(int id) { 
    OrderData orderData = new OrderData(); 
    orderData.setId(id); 
    orderData.setOrderScoreMap(getOrderScore()); 
    return orderData; 
} 
 static Map<String, Double> getOrderScore() { 
     Map<String, Double> map = new HashMap<String, Double>(); 
     for (OrderProperty orderProperty : orderProperties) { 
         if (random.nextInt(10) < 4) continue; 
         if (orderProperty.isTrueOrFalse()) { 
             map.put(orderProperty.getId(), trueFalse[random.nextInt(2)]); 
         } else { 
             map.put(orderProperty.getId(), orderScore[random.nextInt(length)]); 
         } 
     } 
     return map; 
 }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值