您的位置:首页 > 其它

复杂排序-Comparator的应用

2016-01-21 16:09 323 查看
Comparator是java中的比较器, 以前简单的比较或者排序复写一下compareTo就差不多能搞定了.

但是遇到多条件的排序就比较恶心了.

最近在工程中有遇到一个..这边记录一下.希望有点参考价值.

需求是这样的:

用户有很多优惠券,但是优惠券有很多属性.查询后需要给用户最智能的列表.

规则如下: 1.当游戏券面额大于订单总额,额度最低的优先</p>

               2.优惠额度最大的优先</p>

               3.规则1,2相同,子类商户的优先</p>

               4.规则1,2,3相同, 消费金额限制高的优先</p>

               5.规则1,2,3,4相同, 过期时间短的优先</p>

先给出优惠券的类Coupon.javapublic class Coupon {
private String appId;
private String appName;
private String uuid;
private String aid;
private String ano;
private String rechargeNo;
private BigDecimal balance;
private BigDecimal amount;
private Date startTime;
private Date endTime;
private BigDecimal denomination;
private String desc;
private Date createTime;
private int version;
private int rechargeVersion;
private String taskId;

private String note;

public Coupon() {
}

public Coupon(String appId, String appName, String uuid, String aid, String ano, String rechargeNo,
BigDecimal balance, BigDecimal amount, Date startTime, Date endTime, BigDecimal denomination,
String desc, Date createTime, int version, int rechargeVersion, String taskId, String note,
String rule, String status) {
super();
this.appId = appId;
this.appName = appName;
this.uuid = uuid;
this.aid = aid;
this.ano = ano;
this.rechargeNo = rechargeNo;
this.balance = balance;
this.amount = amount;
this.startTime = startTime;
this.endTime = endTime;
this.denomination = denomination;
this.desc = desc;
this.createTime = createTime;
this.version = version;
this.rechargeVersion = rechargeVersion;
this.taskId = taskId;
this.note = note;
this.rule = rule;
this.status = status;
}

/**
* 优惠券使用规则,json字符串,形如:{ "api_key": "使用范围, 某个应用的编号或者其父级应用的编号","use_amount": "触发游优惠券使用的最小金额,精确到小数点后两位"}'
*/
private String rule;

private String status;

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}

public String getAppName() {
return appName;
}

public void setAppName(String appName) {
this.appName = appName;
}

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

public String getAid() {
return aid;
}

public void setAid(String aid) {
this.aid = aid;
}

public String getAno() {
return ano;
}

public void setAno(String ano) {
this.ano = ano;
}

public String getRechargeNo() {
return rechargeNo;
}

public void setRechargeNo(String rechargeNo) {
this.rechargeNo = rechargeNo;
}

public BigDecimal getBalance() {
return balance;
}

public void setBalance(BigDecimal balance) {
this.balance = balance;
}

public BigDecimal getAmount() {
return amount;
}

public void setAmount(BigDecimal amount) {
this.amount = amount;
}

public Date getStartTime() {
return startTime;
}

public void setStartTime(Date startTime) {
this.startTime = startTime;
}

public Date getEndTime() {
return endTime;
}

public void setEndTime(Date endTime) {
this.endTime = endTime;
}

public BigDecimal getDenomination() {
return denomination;
}

public void setDenomination(BigDecimal denomination) {
this.denomination = denomination;
}

public String getDesc() {
return desc;
}

public void setDesc(String desc) {
this.desc = desc;
}

public Date getCreateTime() {
return createTime;
}

public void setCreateTime(Date createTime) {
this.createTime = createTime;
}

public int getVersion() {
return version;
}

public void setVersion(int version) {
this.version = version;
}

public int getRechargeVersion() {
return rechargeVersion;
}

public void setRechargeVersion(int rechargeVersion) {
this.rechargeVersion = rechargeVersion;
}

public String getTaskId() {
return taskId;
}

public void setTaskId(String taskId) {
this.taskId = taskId;
}

public String getRule() {
return rule;
}

public void setRule(String rule) {
this.rule = rule;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

@Override
public String toString() {
return "Coupon [appId=" + appId + ", appName=" + appName + ", uuid=" + uuid + ", aid=" + aid
+ ", ano=" + ano + ", rechargeNo=" + rechargeNo + ", balance=" + balance + ", amount="
+ amount + ", startTime=" + startTime + ", endTime=" + endTime + ", denomination="
+ denomination + ", desc=" + desc + ", createTime=" + createTime + ", version=" + version
+ ", rechargeVersion=" + rechargeVersion + ", taskId=" + taskId + ", note=" + note
+ ", rule=" + rule + ", status=" + status + "]";
}



然后关键的排序..给一个List,然后输出排好序的List

public static List<Coupon> sortCouponList(List<Coupon> validCouponList, BigDecimal orderAmount, String appId) {
List<Coupon> sortedCouponList = new ArrayList<Coupon>();
// 面额大于订单总额筛选
List<Coupon> amountCouponList = new ArrayList<Coupon>();
List<Comparator<Coupon>> amountAscCompare = new ArrayList<Comparator<Coupon>>();
amountAscCompare.add(compareDenominationASC); // 根据金钱升序排列
amountAscCompare.add(compareAppId); // 根据券的使用范围排列
amountAscCompare.add(compareUseAmount); // 根据使用金额限制排列
amountAscCompare.add(compareTime); // 根据过期时间排列
for (Coupon amountCoupon : validCouponList) {
if (orderAmount.compareTo(amountCoupon.getDenomination()) <= 0) {
amountCouponList.add(amountCoupon);
}
}
sort(amountCouponList, amountAscCompare);
validCouponList.removeAll(amountCouponList);
sortedCouponList.addAll(amountCouponList);
// 面额小于订单总额筛选
List<Comparator<Coupon>> amountDescCompare = new ArrayList<Comparator<Coupon>>();
amountDescCompare.add(compareDenominationDESC); // 根据金钱降序序排列
amountDescCompare.add(compareAppId); // 根据券的使用范围排列
amountDescCompare.add(compareUseAmount); // 根据使用金额限制排列
amountDescCompare.add(compareTime); // 根据过期时间排列
sort(validCouponList, amountDescCompare);
sortedCouponList.addAll(validCouponList);
return sortedCouponList;
}

这里先设置一个比较器的List, 将需要比较的项目生成比较器放进List, 根据比较器的权重关系,一个一个循环去比较.
下面是生成的5个比较器private final static Comparator<Coupon> compareDenominationDESC = new Comparator<Coupon>() {
@Override
public int compare(Coupon one, Coupon two) {
if (one.getDenomination().compareTo(two.getDenomination()) < 0) {
return 1;
} else if (one.getDenomination().compareTo(two.getDenomination()) > 0) {
return -1;
} else {
return 0;
}
}
};

private final static Comparator<Coupon> compareDenominationASC = new Comparator<Coupon>() {
@Override
public int compare(Coupon one, Coupon two) {
if (one.getDenomination().compareTo(two.getDenomination()) > 0) {
return 1;
} else if (one.getDenomination().compareTo(two.getDenomination()) < 0) {
return -1;
} else {
return 0;
}
}
};

private final static Comparator<Coupon> compareTime = new Comparator<Coupon>() {
@Override
public int compare(Coupon one, Coupon two) {
if (one.getEndTime().after(two.getEndTime())) {
return 1;
} else if (one.getEndTime().before(two.getEndTime())) {
return -1;
} else {
return 0;
}
}
};

private final static Comparator<Coupon> compareAppId = new Comparator<Coupon>() {
@Override
public int compare(Coupon one, Coupon two) {
JSONObject ruleJsonOne = (JSONObject) JSONValue.parse(one.getRule());
CouponRangeVo couponRangeOne = new CouponRangeVo();
JSONObject ruleJsonTwo = (JSONObject) JSONValue.parse(two.getRule());
CouponRangeVo couponRangeTwo = new CouponRangeVo();
try {
couponRangeOne = DbUtil.getCouponRangeByAppId((String) ruleJsonOne.get("api_key"));
couponRangeTwo = DbUtil.getCouponRangeByAppId((String) ruleJsonTwo.get("api_key"));
} catch (Exception e) {
logger.error("compareAppId error", e);
return 0;
}
if (couponRangeOne == null || couponRangeTwo == null) {
return 0;
}
if (couponRangeOne.getAppId().equals(couponRangeTwo.getAppId())) {
return 0;
} else if (couponRangeOne.getAppId().equals(couponRangeOne.getParentAppId())) {
return 1;
} else {
return -1;
}
}
};

private final static Comparator<Coupon> compareUseAmount = new Comparator<Coupon>() {
@Override
public int compare(Coupon one, Coupon two) {
JSONObject ruleOne = (JSONObject) JSONValue.parse(one.getRule());
JSONObject ruleTwo = (JSONObject) JSONValue.parse(two.getRule());
try {
if (new BigDecimal((String) ruleOne.get("use_amount")).compareTo(new BigDecimal((String) ruleTwo
.get("use_amount"))) < 0) {
return 1;
} else if (new BigDecimal((String) ruleOne.get("use_amount")).compareTo(new BigDecimal(
(String) ruleTwo.get("use_amount"))) > 0) {
return -1;
} else {
return 0;
}
} catch (Exception e) {
logger.error("compareUseAmount error", e);
return 0;
}
}
};
再贴出根据比较器列表进行排序的方法.private static void sort(List<Coupon> list, final List<Comparator<Coupon>> comList) {
if (comList == null) {
return;
}
Comparator<Coupon> cmp = new Comparator<Coupon>() {
@Override
publicint compare(Coupon o1, Coupon o2) {
for (Comparator<Coupon> comparator : comList) {
if (comparator.compare(o1, o2) == 0) {
continue;
} else if (comparator.compare(o1, o2) > 0) {
return 1;
} else if (comparator.compare(o1, o2) < 0) {
return -1;
}
}
return 0;
}
};
Collections.sort(list, cmp);
}

通过循环进行筛选,权重高的先比较,排序高就return出去,排序一样就continue到下一个比较器.这样一层一层下去

总体来说不是很难.但是比较烦..

以后有类似的情况可以参考..
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: