【问题标题】:Java 8 JPA Repository Stream produce two (or more) results?Java 8 JPA Repository Stream 产生两个(或更多)结果?
【发布时间】:2017-08-31 12:03:58
【问题描述】:

我有一个由 Spring Data JPA 存储库返回的 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
}

我需要取出“Beta”对象并对其进行一些工作。所以我想我不得不重复代码,这似乎完全错误:

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

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

【问题讨论】:

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


    【解决方案1】:

    您始终可以通过将常用部分放入方法并将不常用部分转换为参数来重构代码。例如

    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
    

    请注意,这会将“对...的操作”部分从try 块中拉出,这是一件好事,因为这意味着相关资源已被更早地释放。这要求BetaComponent 可以独立于Stream 的底层资源进行处理(否则,无论如何都不应该将它收集到Set 中)。对于Longs,我们确信它们可以独立处理。

    当然,即使不将公共代码移动到方法中,您也可以处理 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
    

    【讨论】:

      猜你喜欢
      • 2013-09-23
      • 2020-01-07
      • 1970-01-01
      • 2020-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      相关资源
      最近更新 更多