Java实现:将列表公共元素前置并整体升序排序
问题描述
我有两个存储名称的列表:
- 第一个列表
l1包含选定名称 - 第二个列表
l2包含全部名称
示例代码:
List<String> l1 = {"en", "cu", "eu"}; List<String> l2 = {"ch", "cu", "en", "eu", "pe"};
已知l1中的所有元素均存在于l2中。
需要生成符合以下要求的输出列表:
- 所有公共名称(即同时存在于
l1和l2中的元素)放在列表开头 l2中剩余的元素紧随其后- 公共元素部分和剩余元素部分各自按升序排列
示例输出:
output -> {cu, en, eu, ch, pe};
我尝试了以下代码,但不知道如何将公共元素放在开头、剩余元素放在后面(l2已排序):
List<String> common = l2.stream().filter(l2::contains).collect(Collectors.toList());
解决方案
方案一:分步处理(逻辑清晰)
先分别处理公共元素和剩余元素,再合并:
// 优化:将l1转为HashSet提升contains效率 Set<String> l1Set = new HashSet<>(l1); // 1. 排序l1中的元素(即所有公共元素) List<String> sortedCommon = l1.stream() .sorted() .collect(Collectors.toList()); // 2. 提取l2中不在l1里的元素并排序 List<String> sortedRemaining = l2.stream() .filter(item -> !l1Set.contains(item)) .sorted() .collect(Collectors.toList()); // 3. 合并两个列表 List<String> result = new ArrayList<>(); result.addAll(sortedCommon); result.addAll(sortedRemaining);
方案二:自定义比较器(代码简洁)
通过自定义排序规则,一次性完成排序和分组:
Set<String> l1Set = new HashSet<>(l1); List<String> result = l2.stream() .sorted((a, b) -> { boolean aInL1 = l1Set.contains(a); boolean bInL1 = l1Set.contains(b); // 优先把在l1中的元素排在前面 if (aInL1 != bInL1) { return aInL1 ? -1 : 1; } // 同组内按字符串升序排列 return a.compareTo(b); }) .collect(Collectors.toList());
说明
- 把
l1转为HashSet是为了优化contains方法的性能,从O(n)降到O(1),当列表元素较多时效果明显。 - 两种方案都能满足需求,可根据代码风格偏好选择。
内容的提问来源于stack exchange,提问作者jitendra varshney
相关产品推荐
相关产品推荐

