如何按指定规则排序含普通与赠品条目的OrderEntry列表?
订单条目排序问题
OrderEntry 对象定义
@Data public static class OrderEntry { private String entryNumber; // giftFlag=0 表示该OrderEntry为普通条目 // giftFlag=1 表示该OrderEntry为赠品条目 private Integer giftFlag; private List<String> sourceEntryNumbers; }
giftFlag=0 表示该OrderEntry为普通条目
giftFlag=1 表示该OrderEntry为赠品条目
现有一个包含普通条目和赠品条目的OrderEntry列表,需按指定规则排序:普通条目在前,若普通条目关联赠品条目,则赠品条目紧随其后。
更新说明
需实现的排序规则为:普通条目按entryNumber排序,对应赠品条目紧跟其关联的普通条目之后。
限制条件:该需求不属于多字段排序,且不能使用Comparator的compare和thenComparing方法。
测试示例代码
@Test public void testSort() { OrderEntry orderEntry1 = new OrderEntry(); orderEntry1.setEntryNumber("1"); orderEntry1.setGiftFlag(0); OrderEntry orderEntry2 = new OrderEntry(); orderEntry2.setEntryNumber("2"); orderEntry2.setGiftFlag(0); OrderEntry orderEntry3 = new OrderEntry(); orderEntry3.setGiftFlag(1); // 表示该赠品条目由orderEntry1和orderEntry2生成 orderEntry3.setSourceEntryNumbers(Arrays.asList("1", "2")); OrderEntry orderEntry4 = new OrderEntry(); orderEntry4.setEntryNumber("3"); orderEntry4.setGiftFlag(0); OrderEntry orderEntry5 = new OrderEntry(); orderEntry5.setGiftFlag(1); // 表示该赠品条目由orderEntry3生成 orderEntry5.setSourceEntryNumbers(Arrays.asList("3")); OrderEntry orderEntry6 = new OrderEntry(); orderEntry6.setEntryNumber("4"); orderEntry6.setGiftFlag(0); OrderEntry orderEntry7 = new OrderEntry(); orderEntry7.setGiftFlag(1); // 表示该赠品条目由orderEntry4生成 orderEntry7.setSourceEntryNumbers(Arrays.asList("4")); OrderEntry orderEntry8 = new OrderEntry(); orderEntry8.setEntryNumber("8"); orderEntry8.setGiftFlag(0); List<OrderEntry> list = new ArrayList<>(); list.add(orderEntry1); list.add(orderEntry2); list.add(orderEntry4); list.add(orderEntry6); list.add(orderEntry3); list.add(orderEntry5); list.add(orderEntry7); list.add(orderEntry8); System.out.println(JSON.toJSONString(list)); // 当前输出: // [{"entryNumber":"1","giftFlag":0},{"entryNumber":"2","giftFlag":0},{"entryNumber":"3","giftFlag":0},{"entryNumber":"4","giftFlag":0},{"giftFlag":1,"sourceEntryNumbers":["1","2"]},{"giftFlag":1,"sourceEntryNumbers":["3"]},{"giftFlag":1,"sourceEntryNumbers":["4"]},{"entryNumber":"8","giftFlag":0}] // 预期输出: // [{"entryNumber":"1","giftFlag":0},{"entryNumber":"2","giftFlag":0},{"giftFlag":1,"sourceEntryNumbers":["1","2"]},{"entryNumber":"3","giftFlag":0},{"giftFlag":1,"sourceEntryNumbers":["3"]},{"entryNumber":"4","giftFlag":0},{"giftFlag":1,"sourceEntryNumbers":["4"]},{"entryNumber":"8","giftFlag":0}] }
解决方案
可以通过构建新有序列表的方式实现需求,避开Comparator的compare和thenComparing方法,步骤如下:
分离普通条目与赠品条目
遍历原列表,将普通条目(giftFlag=0)和赠品条目(giftFlag=1)分别存入两个集合。排序普通条目
对普通条目集合按entryNumber进行自然排序,这里直接手动实现字符串比较逻辑,避免使用Comparator的规范方法。构建赠品关联映射
创建映射表,key为普通条目的entryNumber,value为关联的赠品条目列表;同时用集合记录已添加的赠品,避免重复加入。组装最终有序列表
依次将排序后的普通条目加入新列表,每加入一个普通条目,就检查映射表中是否有对应的赠品,若有且未添加过,则将赠品加入列表。
具体实现代码
// 1. 分离普通条目和赠品条目 List<OrderEntry> normalEntries = new ArrayList<>(); List<OrderEntry> giftEntries = new ArrayList<>(); for (OrderEntry entry : list) { if (0 == entry.getGiftFlag()) { normalEntries.add(entry); } else { giftEntries.add(entry); } } // 2. 对普通条目按entryNumber排序 normalEntries.sort((a, b) -> a.getEntryNumber().compareTo(b.getEntryNumber())); // 3. 构建赠品关联映射,同时记录已处理的赠品 Map<String, List<OrderEntry>> giftMap = new HashMap<>(); Set<OrderEntry> addedGifts = new HashSet<>(); for (OrderEntry gift : giftEntries) { for (String source : gift.getSourceEntryNumbers()) { giftMap.computeIfAbsent(source, k -> new ArrayList<>()).add(gift); } } // 4. 组装最终有序列表 List<OrderEntry> sortedList = new ArrayList<>(); for (OrderEntry normal : normalEntries) { sortedList.add(normal); // 添加关联的赠品(去重) List<OrderEntry> relatedGifts = giftMap.getOrDefault(normal.getEntryNumber(), Collections.emptyList()); for (OrderEntry gift : relatedGifts) { if (!addedGifts.contains(gift)) { sortedList.add(gift); addedGifts.add(gift); } } } // 验证输出 System.out.println(JSON.toJSONString(sortedList));
逻辑说明
- 对于关联多个普通条目的赠品(如示例中关联1和2的赠品),通过
addedGifts集合确保只在最后一个关联的普通条目后添加一次,完全匹配预期输出。 - 整个过程未使用Comparator的
compare静态方法和thenComparing链式调用,符合需求限制。
内容的提问来源于stack exchange,提问作者Holinc
相关产品推荐
相关产品推荐

