本排序适用于内存排序,并且有强制的优先级
比如 有秒杀活动的 > 加入购物车 > 运营元素 > 店铺评分 > 历史购买 > 普通活动
本功能用户实际项目中搜索的展现以及推荐(当然优先级没有上面列的那么简单)
该版本性能还可以继续提供,因为时间有限,所以先出一个版本
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, Comparable> orderScoreMap; /** * 属性 */ private Map , 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 , 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 , Double> map) { Set , Double>> entrySet = map.entrySet(); for (Map.Entry , 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{ /** * 要素标识 */ 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{ private List orderProperties; public OrderDataComparator(List 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(ListT>> orderDatas, List orderProperties, int max) { //将要素要优先级排序, 优先级高的排在前面 Collections.sort(orderProperties); sort(orderDatas, new OrderDataComparator(orderProperties), max); } /** * * @param list * @param comparator * @param maxSize */ public static <T> void sort(List T>> list, Comparator 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 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 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(ListT>> orderDatas, List orderProperties); /** * 按照top max 排序 * @param orderDatas * @param orderProperties * @param maxSize * @param <T> * @return */ public abstract <T> List<T> sortMax(List T>> orderDatas, List orderProperties, int maxSize); /** * 分页排序 * @param orderDatas * @param orderProperties * @param pageNo * @param pageSize * @param <T> * @return */ public abstract <T> List<T> sortPaging(List T>> orderDatas, List orderProperties, int pageNo, int pageSize); /** * 获取id * @param orderDatas * @param start * @param end * @return */ public final <T> List<T> getIds(List 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(ListT>> orderDatas, List orderProperties) { if (CollectionUtils.isEmpty(orderDatas)) return null; return sortMax(orderDatas, orderProperties, orderDatas.size()); } @Override public <T> List<T> sortMax(List T>> orderDatas, List 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 T>> orderDatas, List 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> 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
littlehow写于 2017-08-18 14:55