Java 11 Lambda按ID分组后优先筛选PROPERTY为A的实体实现方案
解决思路:用Stream groupingBy + 自定义收集器
嘿,这个需求用Java Stream API完全能搞定,你选groupingBy的思路是对的,关键是搭配合适的收集器来处理每个分组内的元素——我们的目标是优先保留PROPERTY为"A"的实体,如果组里没有"A"才保留"Z"。
先明确实体类(假设你有这样的类)
首先定义一下我们操作的实体类,方便后续代码示例:
class Entity { private String id; private String property; // 构造器、getter方法 public Entity(String id, String property) { this.id = id; this.property = property; } public String getId() { return id; } public String getProperty() { return property; } // 重写toString方便查看结果 @Override public String toString() { return id + " | " + property; } }
方案1:用collectingAndThen + 过滤查找
这种方式逻辑最直观:先按ID分组,对每个分组的元素列表,先筛选出"A"的实体,找到第一个就返回;如果没有,再筛选"Z"的实体返回。
import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Entity> list = Arrays.asList( new Entity("FOO", "A"), new Entity("FOO", "Z"), new Entity("JOHN", "A"), new Entity("DOE", "Z") ); List<Entity> result = list.stream() .collect(Collectors.groupingBy(Entity::getId, Collectors.collectingAndThen( Collectors.toList(), entities -> entities.stream() .filter(e -> "A".equals(e.getProperty())) .findFirst() .orElseGet(() -> entities.stream() .filter(e -> "Z".equals(e.getProperty())) .findFirst() .orElse(null)) // 可根据业务调整,比如抛异常 ) )) .values() .stream() .filter(Objects::nonNull) .collect(Collectors.toList()); // 打印结果 result.forEach(System.out::println); } }
方案2:用maxBy + 自定义比较器(更简洁)
我们可以给"A"设置更高的优先级,用maxBy收集器来选出分组内优先级最高的实体:
List<Entity> result = list.stream() .collect(Collectors.groupingBy(Entity::getId, Collectors.maxBy(Comparator.comparing(e -> "A".equals(e.getProperty()) ? 1 : 0)) )) .values() .stream() .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList());
这里的逻辑是:给PROPERTY为"A"的实体赋值优先级1,"Z"赋值0,maxBy会自动选出优先级更高的实体;如果分组里没有"A",就会选"Z"的实体。
运行结果
两种方案运行后都会输出你期望的结果:
FOO | A JOHN | A DOE | Z
内容的提问来源于stack exchange,提问作者Fabrizio Stellato
相关产品推荐
相关产品推荐

