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

来源:互联网 发布:星游记网络大电影 编辑:程序博客网 时间:2024/05/18 01:31

 本排序适用于内存排序,并且有强制的优先级

比如  有秒杀活动的 > 加入购物车 > 运营元素 > 店铺评分 > 历史购买 > 普通活动

本功能用户实际项目中搜索的展现以及推荐(当然优先级没有上面列的那么简单)


该版本性能还可以继续提供,因为时间有限,所以先出一个版本


csdn code 地址 :   https://code.csdn.net/w172087242/littlehow/tree/master/src/main/java/littlehow/sort/group


排序元素准备:

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;    }}


OrderProperty 排序要素

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 = id;        this.ordinal = ordinal;        //默认倒序        this.orderDirect = 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 + "}";    }}


OrderDataComparator主要用于因子值之间的排序

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 OrderDataComparator(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;    }}

utils包下

SortUtils 主要排序工具

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);    }}

CollectionUtils 集合工具,可以使用其他开源的集合工具,主要是不希望依赖太多

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;    }}

service包下

SortService排序接口,主要便于以后扩展排序实现使用

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;    }}

GroupSortService 分组排序实现类

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);    }}

test包下

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; }}

littlehow写于 2017-08-18 14:55

原创粉丝点击