
本文将深入探讨如何使用 Java Stream API 中的 distinct() 方法来检查列表中是否存在重复值,并解决在实际应用中可能遇到的 BadRequestException 异常。通过分析一个具体的代码示例,我们将找出问题根源,并提供相应的解决方案,确保列表去重操作的正确性和稳定性。
问题分析
原始代码中使用 stream.distinct().count() != cheminementForm.getPositionsPoste().size() 来判断 positionsPoste 列表中是否存在重复值。虽然 distinct() 方法能够去除流中的重复元素,但如果列表中包含 null 值,则可能导致判断错误,从而抛出 BadRequestException 异常,即使列表中实际上没有重复的非空元素。
解决方案
根本问题在于列表中可能包含 null 值,而原始代码没有对 null 值进行处理。因此,在进行重复值判断之前,需要先从列表中移除 null 值。可以使用 filter() 方法过滤掉 null 元素。
以下是修改后的代码:
if(cheminementForm.getPositionsPoste().stream().filter(Objects::nonNull).distinct().count() != cheminementForm.getPositionsPoste().stream().filter(Objects::nonNull).count()){
throw new BadRequestException("Cannot have same positions");
}代码解释:
- cheminementForm.getPositionsPoste().stream(): 将 positionsPoste 列表转换为 Stream 流。
- .filter(Objects::nonNull): 使用 filter() 方法过滤掉 Stream 流中的 null 元素。Objects::nonNull 是一个方法引用,等价于 x -> Objects.nonNull(x),用于判断元素是否为 null。
- .distinct(): 对过滤后的 Stream 流进行去重操作,移除重复的元素。
- .count(): 计算去重后的 Stream 流中元素的数量。
- cheminementForm.getPositionsPoste().stream().filter(Objects::nonNull).count(): 计算过滤掉 null 值之后列表的总长度,与去重后的长度进行比较。
完整代码示例:
public Cheminement add(final CheminementForm cheminementForm) throws BadRequestException {
if(cheminementForm == null){
log.error("Cheminement can not be null");
throw new BadRequestException("CheminementForm can not be null");
}else if (Objects.isNull(cheminementForm.getName())){
log.error("All fields must be filled.");
throw new BadRequestException("All fields must be filled.");
}
Cheminement cheminement = Cheminement.builder().disable(false).name(cheminementForm.getName()).build();
List cheminementEtapeList = new ArrayList<>();
List positionsPoste = cheminementForm.getPositionsPoste();
if(positionsPoste != null && positionsPoste.stream().filter(Objects::nonNull).distinct().count() != positionsPoste.stream().filter(Objects::nonNull).count()){
throw new BadRequestException("Cannot have same positions");
}
for(int i=0; i注意事项
-
空指针检查: 在使用 Stream API 之前,务必对列表本身进行空指针检查,避免出现 NullPointerException。
-
数据校验: 在前端或后端对输入数据进行校验,确保列表中不包含 null 值或非法数据,可以从根本上避免此类问题。
-
方法引用: 使用 Objects::nonNull 方法引用可以使代码更简洁易读。
-
性能考虑: 对于大型列表,频繁使用 Stream API 可能会影响性能。可以考虑使用其他更高效的去重算法,例如使用 HashSet。
总结
使用 Stream.distinct() 方法检查列表是否存在重复值时,需要特别注意列表中可能存在的 null 值。通过在去重之前使用 filter() 方法过滤掉 null 元素,可以避免因 null 值导致的判断错误。同时,建议在前端或后端对输入数据进行校验,从根本上保证数据的质量。此外,根据实际情况选择合适的去重算法,以提高程序的性能。










