Java 8 JPA Repository Stream产生两个(或更多)结果?

时间:2017-04-05 18:05:43

标签: java-8 spring-data spring-data-jpa java-stream

我有一个由Spring Data JPA Repository返回的Java 8流。我不认为我的用例是那么不寻常,有两个(在我的情况下实际上是3个),从我想要收集的结果流中收集。

Set<Long> ids = // initialized
try (Stream<SomeDatabaseEntity> someDatabaseEntityStream = 
             someDatabaseEntityRepository.findSomeDatabaseEntitiesStream(ids)) {
    Set<Long> theAlphaComponentIds = someDatabaseEntityStream
            .map(v -> v.getAlphaComponentId())
            .collect(Collectors.toSet());
    // operations on 'theAlphaComponentIds' here
}

我需要推出测试版&#39;对象也做了一些工作。所以我认为我不得不重复代码,这似乎是完全错误的:

try (Stream<SomeDatabaseEntity> someDatabaseEntityStream = 
             someDatabaseEntityRepository.findSomeDatabaseEntitiesStream(ids)) {
    Set<BetaComponent> theBetaComponents = someDatabaseEntityStream
            .map(v -> v.getBetaComponent())
            .collect(Collectors.toSet());
    // operations on 'theBetaComponents' here
}

这两个代码块在处理过程中连续出现。是否有干净的方法让两个集合只处理Stream一次?注意:我不想要一些kludgy解决方案构成Alpha和Beta的包装类,因为它们并不真正属于一起。

1 个答案:

答案 0 :(得分:2)

您可以通过将公共部分放入方法并将不常见的部分转换为参数来重构代码。 E.g。

public <T> Set<T> getAll(Set<Long> ids, Function<SomeDatabaseEntity, T> f)
{
    try(Stream<SomeDatabaseEntity> someDatabaseEntityStream = 
         someDatabaseEntityRepository.findSomeDatabaseEntitiesStream(ids)) {
        return someDatabaseEntityStream.map(f).collect(Collectors.toSet());
    }
}

可通过

使用
Set<Long> theAlphaComponentIds = getAll(ids, v -> v.getAlphaComponentId());
// operations on 'theAlphaComponentIds' here

Set<BetaComponent> theBetaComponents = getAll(ids, v -> v.getBetaComponent());
// operations on 'theBetaComponents' here

请注意,这会将{操作on ... here “部分从try块中拉出来,这是一件好事,因为这意味着相关资源会更早发布。这要求BetaComponent可以独立于Stream的基础资源进行处理(否则,您不应该将其收集到Set中)。对于Long,我们确信它们可以独立处理。

当然,即使没有将公共代码移动到方法中,您也可以从try块处理结果。原始代码是否带有需要重构的重复,这是值得商榷的。实际上,该操作包含try块中的单个语句,该语句由于冗长的标识符而看起来很大。问问自己,如果代码看起来像是

,你是否仍然认为必要的重构
Set<Long> alphaIDs, ids = // initialized
try(Stream<SomeDatabaseEntity> s = repo.findSomeDatabaseEntitiesStream(ids)) {
    alphaIDs = s.map(v -> v.getAlphaComponentId()).collect(Collectors.toSet());
}
// operations on 'theAlphaComponentIds' here

嗯,不同的开发者可能得出不同的结论......

如果您想减少存储库查询的数量,您只需存储查询结果:

List<SomeDatabaseEntity> entities;
try(Stream<SomeDatabaseEntity> someDatabaseEntityStream = 
     someDatabaseEntityRepository.findSomeDatabaseEntitiesStream(ids)) {
    entities=someDatabaseEntityStream.collect(Collectors.toList());
}
Set<Long> theAlphaComponentIds = entities.stream()
  .map(v -> v.getAlphaComponentId()).collect(Collectors.toSet());
// operations on 'theAlphaComponentIds' here
Set<BetaComponent> theBetaComponents = entities.stream()
  .map(v -> v.getBetaComponent()).collect(Collectors.toSet());
// operations on 'theBetaComponents' here