Java8-使用流进行映射而不收集性能 指数增长流

Java8-使用流进行映射而不收集性能 指数增长流,java,lambda,java-8,java-stream,collectors,Java,Lambda,Java 8,Java Stream,Collectors,我有一个流,它以指数方式增长,用于创建置换。因此,每次调用addWeeks都会增加流中的元素数 Stream<SeasonBuilder> sbStream = sbSet.stream(); for (int i = 1; i <= someCutOff; i++) { sbStream = sbStream.map(sb -> sb.addWeeks(possibleWeeks)) .flatMap(Collec

我有一个
,它以指数方式增长,用于创建置换。因此,每次调用
addWeeks
都会增加
流中的元素数

Stream<SeasonBuilder> sbStream = sbSet.stream();

for (int i = 1; i <= someCutOff; i++) {
    sbStream = sbStream.map(sb -> sb.addWeeks(possibleWeeks))
                       .flatMap(Collection::stream); 
}

// Collect SeasonBuilders into a Set
return sbStream.collect(Collectors.toSet());   // size > 750 000 
  • 内存不足错误。。。。。如果可能,周的大小为15

  • 问题
    • 我应该使用方法链而不是
      map
      ,然后是
      flatmap
    • 如何修改
      addWeeks
      ,使我不必将所有内容收集到
      集合中
      • 我是否应该返回
        ?我可以
        flatmap
        a
        Stream
    更新: 谢谢大家的帮助

    我已经将这些方法的代码放在

    感谢@Holger和@lexicore建议在
    addWeeks
    中返回
    。正如@lexicore所预测的,性能略有提高

    我尝试使用
    parallelStream()
    ,但性能没有明显变化

    上下文 我正在创建一个赛季的所有可能的排列,这些排列将在其他地方用于统计分析。在一个4队14周的赛季中,对于任何给定的一周,可能有三种不同的可能性

    • (1对2),(3对4)
    • (1对3),(2对4)
    • (1对4),(2对3)
    为了解决这个问题,插入排列,我们就有了所有可能的季节。完成!但是等等。。。如果第一队只和第二队比赛呢。然后其他球队会很伤心。所以在排列上有一些限制

    每支球队之间的比赛次数必须大致相同(即1队不能在一个赛季内与3队比赛10次)。在这个例子中——4个队,14周——每个队最多与另一队比赛5次。因此,在创建排列时必须进行某种过滤,以避免无效的季节

    更有趣的是:

    • 6个团队联盟——15个可能的星期
    • 8队联赛——105周
    • 10支球队联盟——945个可能的星期

    我正在尽可能优化性能,因为有很多排列需要创建。考虑到限制因素,一个4队14周的赛季创造了756756个可能的赛季。6队或8队赛季变得更加疯狂。

    你的整个结构一开始就非常可疑。如果您对性能感兴趣,那么显式生成所有置换不太可能是一种好方法

    我也不认为再次收集设置和流媒体是性能问题

    但是,为了回答您的问题:为什么不直接从
    addWeeks
    返回
    Stream
    ,为什么要先收集它?直接返回流,不收集:

    public Stream<SeasonBuilder> addWeeks(
        final Set<Set<ImmutablePair<Integer, Integer>>> possibleWeeks) {
            return possibleWeeks.stream()
                    .filter(containsMatchup())   // Finds the weeks to add
                    .map(this::addWeek);   // Create new SeasonBuilders with the new week
    }
    

    但这对你的表现没有多大帮助。

    那么你想实现什么呢?如果你想要一个快速的东西,生成所有排列很可能不是最好的开始方法。很明显,你必须如何更改
    addWeeks
    ?让它返回元素的
    ,而不是
    (并将名称更改为反映其实际功能的名称,因为它显然不
    添加…
    )。除非你想重新设计一切,包括你在问题中没有提到的东西,否则这是唯一可能的改变。无论您是使用
    map
    ,然后是
    flatMap
    ,还是使用单个
    flatMap
    ,都是无关紧要的。@alexdriedger将任何>750_000个元素收集到任何数据结构都会很慢,添加排列只会让事情变得更糟。霍尔格是对的,除非你用简单的语言解释你想要达到的目标,否则很难给出任何建议。@霍尔格,你介意回答这个问题吗?我认为,当你实例化你的流时,激活并行流将是一个很好的促进。尝试一下,并给我反馈。你是正确的,再次收集和流媒体不是主要的性能问题。我根据你的建议再次运行了它,它的性能略有提高
    public Stream<SeasonBuilder> addWeeks(
        final Set<Set<ImmutablePair<Integer, Integer>>> possibleWeeks) {
            return possibleWeeks.stream()
                    .filter(containsMatchup())   // Finds the weeks to add
                    .map(this::addWeek);   // Create new SeasonBuilders with the new week
    }
    
    sbStream = sbStream.flatMap(sb -> sb.addWeeks(possibleWeeks));