话不多说,直接上。
需求:根据一定规则获取前几(top N)的供应商(商户,啥的都可以)。
背景:供应商有等级level,评分 rank,距离维度。
实现步骤:
// 1. 根据等级分组
Map<Integer, List<SupplierService.Supplier>> supplierLevelMap = allSupplierList.stream().filter(e -> e.getLevel() != null) .sorted(Comparator.comparing(SupplierService.Supplier::getLevel)) .collect(Collectors.groupingBy(e -> e.getLevel(), LinkedHashMap::new, Collectors.toList()));
// 2. 遍历等级从有评分的供应商中选
for (Integer level : supplierLevelMap.keySet()) {
List<SupplierService.Supplier> supplierList = supplierLevelMap.get(level);
if (CollectionUtils.isEmpty(supplierList)) {
continue;
}
// 按照供应商评分倒序
List<SupplierService.Supplier> sortedSupplierList = supplierList.stream().filter(e -> e.getRank() != null)
.sorted(Comparator.comparing(SupplierService.Supplier::getRank).reversed()).collect(Collectors.toList());
if (CollectionUtils.isEmpty(sortedSupplierList)) {
continue;
}
BigDecimal preScore = new BigDecimal("0");
for (SupplierService.Supplier supplier : sortedSupplierList) {
BigDecimal score = supplier.getRank();
if (null == score) {
continue;
}
// 下一个分数,且数已经满足,直接返回集合
if (preScore.compareTo(score) != 0 && afterFilterSupplierList.size() >= inquirySupplierNum) {
return afterFilterSupplierList;
}
// 不判断该供应商是否超出限制
afterFilterSupplierList.add(supplier.getSupplierId());
}
}
// 3.有评分的还未满足,从没有评分的选,距离近的优先
if (afterFilterSupplierList.size() < inquirySupplierNum) {
for (Integer level : supplierLevelMap.keySet()) {
List<SupplierService.Supplier> supplierList = supplierLevelMap.get(level);
if (CollectionUtils.isEmpty(supplierList)) {
continue;
}
Integer needSupplierNum = inquirySupplierNum - afterFilterSupplierList.size();
// 按照供应商距离排序
List<Long> sortedSupplierIdList = supplierList.stream()
.filter(e -> e.getRank() == null)
.map(e -> calDistance(e, clientUserId))
.sorted(Comparator.comparing(SupplierService.Supplier::getDistance))
.map(SupplierService.Supplier::getSupplierId)
.limit(needSupplierNum).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(sortedSupplierIdList)) {
afterFilterSupplierList.addAll(sortedSupplierIdList);
}
}
}