在Java 8流中添加具有map和count的过滤器

时间:2019-07-19 12:33:44

标签: java java-8 java-stream

有一个对象列表。要求是

  1. 添加过滤器以检查字段是否已初始化
  2. 添加地图以获取对象列表中的特定字段
  3. 添加一个计数检查,条件是以上字段的计数应为1(列表中的唯一值)。
  4. 如果满足条件3,则返回该字段的值,否则返回null

现在,我分两步实现上述目标,在步骤1中过滤出初始化值列表。在步骤2中,使用此列表并在列表中找到具有唯一值的值,否则返回null

面对问题,当我将两者结合时,不应在计数之前过滤元素。

List<CarDetails> carDetails = 
   carDetails.stream().filter(
   carDTO -> 
   carDTO.isInitialized(CarDetail.Fields.CAR_ID.getCode())).collect(Collectors.toList());

if (CollectionUtils.isNotEmpty(carDetails))
{
   carId =(carDetails.stream().map(CarlDetail::getCarId).distinct().count() > 1) 
          ? null:carDetails.get(0).getCarId();
}

例如: 列出CarDetails-CarId

{3,4,null}  ---o/p= null (since id is not unique)
{3,null}    ---o/p= null (since id is not unique - has 3 and null)
{3,3,3}     ---o/p= 3 (since id is unique)

请让我知道如何在列表中存在空值的情况下,通过获取并通过不获取空指针的过滤器来实现上述目的

2 个答案:

答案 0 :(得分:0)

我只想演示您(使用预过滤的)对象列表可以做什么:

list.stream()
   .filter(aPredicate)
   .map(anExtractionFunction)
   .distinct()
   .collect(Collectors.collectingAndThen(
            Collectors.counting(), c -> c == 1 ? someValue : someFallbackValue))

如果只有一个唯一元素,则返回someValue,否则返回someFallbackValue

也许这对您有帮助。

答案 1 :(得分:0)

不需要计数元素。由于您只关心ID,并且需要唯一ID,因此只需使用

carID = carDetails.stream()
    .filter(carDTO -> carDTO.isInitialized(CarDetail.Fields.CAR_ID.getCode()))
    .map(cd -> Optional.ofNullable(cd.getCarId()))
    .reduce((a,b) -> a.equals(b)? a: Optional.empty())
    .flatMap(Function.identity())
    .orElse(null);

由于此操作仅对id感兴趣,因此在归约之前直接映射到getCarId()。但是我们必须将这些值包装到Optional中,因为没有身份值的reduce不支持null结果值。

然后,我们将所有值减小为一个。如果id相等,则使用它们中的任何一个,否则,将它们替换为空的可选值。空的可选内容不等于非空的可选内容。两个空的可选内容是相等的,但是映射到它们中的任何一个都会再次导致空的可选内容。因此,在将空的可选内容映射到null之后,如果ID为null的情况下映射到null的要求就会自动得到满足。