【问题标题】:Java streaming higher order functionJava流高阶函数
【发布时间】:2019-03-18 16:32:34
【问题描述】:

我正在尝试处理具有 2 层深度的嵌套列表的对象。例如我的对象可以分解成这样的:

TopLevel: [
    MidLevel: [
        LowLevel,
        LowLevel,
        .
        .
    ],
    MidLevel: [
        LowLevel,
        LowLevel,
        .
        .
    ]
    .
    .
]

基本上TopLevel 包含MidLevel 对象的列表,而每个对象又包含LowLevel 对象的列表。在处理结束时,我想为每个LowLevel 对象构建SomeObj。但是SomeObj 需要来自TopLevelMidLevelLowLevel 的信息。

在过去的几个月里,我一直在尝试以更实用的风格编写代码,所以我的第一个想法是创建一个可以在对象的每个级别上构建的高阶函数。函数如下所示:

Function<MidLevel, Function<LowLevel, SomeObj>> buildObjects(TopLevel topLevel) {
    return midLevel ->
        lowLevel -> {
            return buildSomeObj(topLevel, midLevel, lowLevel);
        };
}

我打算以如下方式使用这个函数(假设我有提供列表流的实用函数):

Function<MidLevel, Function<LowLevel, SomeObj>> topBuilder = buildObjects(topLevel);
List<SomeObj> objs = topLevel.streamMid()
    .map(topBuilder)
    .streamLow()
    .map(Function::apply)
    .collect(/*collect to list*/);

但是,这显然不起作用,因为一旦我将 MidLevel 对象应用于 topBuilder 函数,我的流现在是函数流而不是 MidLevel 对象,因此我无法访问列表LowLevel 流中的对象不再存在。

是否有任何解决方案,或者当它不太适合它时,我是否正在尝试在功能上解决这个问题?有没有办法既应用该函数,又可以访问应用于该函数的原始对象?

【问题讨论】:

    标签: java functional-programming java-stream


    【解决方案1】:

    flatMap() 和嵌套是要走的路。试试这个:

    topLevelStream() //create a stream of top level elements
      .flatMap( top -> top.streamMid() //create a stream of mid level elements
        .flatMap( mid -> mid.streamLow() //create a stream of low level elements
          .map(low -> "use top, mid and low here") 
        ) 
      )
      .collect( ... );
    

    通过这样的嵌套,您仍然可以访问外部函数中的元素,并且flatMap()map() 的组合将调用map() 的流公开给collect()

    【讨论】:

    • 如果我正确理解了这个问题,那么没有顶级流本身,因此单个flatMap 应该这样做。
    • @Naman 你是对的,虽然适应这不应该是一个大问题:)
    【解决方案2】:

    您可以简单地将flatMap 用作:

    List<SomeObj> objs = topLevel.getMidLevels().stream()
            .flatMap(a -> a.getLowLevels().stream().map(b -> topBuilder.apply(a).apply(b)))
            .collect(Collectors.toList());
    

    您的实体类似于:

    class TopLevel {
        List<MidLevel> midLevels;
    }
    
    class MidLevel {
        List<LowLevel> lowLevels;
    }
    
    class LowLevel {
    }
    
    class SomeObj {
    }
    

    【讨论】:

    • 旁白:您的buildObjects 实现看起来比return midLevel -&gt; lowLevel -&gt; buildSomeObj(topLevel, midLevel, lowLevel) 更好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    相关资源
    最近更新 更多