【问题标题】:Facing Issues in Java Higher Order Function. Not reaping the correct benefit of higher order functionJava高阶函数面临的问题。没有从高阶函数中获得正确的好处
【发布时间】:2020-10-22 17:59:13
【问题描述】:

我们需要获取所有具有特定操作的项目的列表。我知道我没有使用正确的高阶函数方法。需要了解如何使用高阶函数改进第三种解决方案,以及为什么这会花费太多时间。

解决方案 1:在没有任何 java 8 函数式编程的情况下使用深度优先搜索递归

花费时间 0.07 毫秒

 getitemsDFS(ItemRef po)
     {
           List<ItemRef> items = new ArrayList<>();
           for(Item child : po.getItem())
           {
                items.addAll(getAdditemsRec(child));
           }
           return items;
     }

 private List<ItemRef> getAdditemsRec(ItemRef child) {
       List<ItemRef> items = new ArrayList<>();
       if(SOME_ACTION.equals(child.getAction()))
       {
            items.add(child);
       }
       for(ItemRef childOI: child.getItem())
       {
            items.addAll(getAdditemsRec(childOI));
       }
       return items;
 }

解决方案 2:在没有任何 java 8 函数式编程的情况下使用广度优先搜索

花费时间 0.05 毫秒

 private List<ItemRef> getAddOrderItemBFS(Item po) {
               
               List<ItemRef> items = new ArrayList<>();
               Deque<ItemRef> oIDeque = new ArrayDeque<>();
               oIDeque.addAll(po.getItem());
               while(!oIDequ

e.isEmpty())


   {
            ItemRef currentOI = oIDeque.removeFirst();
            if(ADD_ACTION.equals(currentOI.getAction()))
                  items.add(currentOI);
            if(!CollectionUtils.isEmpty(currentOI.getItem()))
                  oIDeque.addAll(currentOI.getItem());
       }
       return items;
 }

解决方案 3:使用函数式编程和 Lambda 表达式 11.50 毫秒

这是大约。比 1 和 2 多 200 倍,我们需要对此进行优化。 它也不是纯函数式编程,因为它涉及 ArrayList 创建和分配代码和命令式代码(事情如何 完成,而不仅仅是需要做的事情)。没有收获正确 高阶函数的好处。

private List<ItemRef> getAdditemsFunctional(ItemRef po)
     {
           return po
                      .getItem()
                      .stream()
                      .map(oi->getitemsFunctionalRec(oi))
                      .flatMap(List::stream)
                      .collect(Collectors.toList());
     }

private List<ItemRef> getitemsFunctionalRec(ItemRef oi) {
           List<ItemRef> listOIs = new ArrayList<>();
           if(ADD_ACTION.equals(oi.getAction()))
           {
                listOIs.add(oi);
           }
           listOIs.addAll(oi.getItem()
                      .stream()
                      .map(childOI->getitemsFunctionalRec(childOI))
                      .flatMap(List::stream)
                      .collect(Collectors.toList()));
           return listOIs;
     }

【问题讨论】:

  • 所以你有一个递归数据结构(像一棵树)并且想要将它展平并从中过滤掉一些数据?我是否正确理解了这个问题?
  • 是的,@Amongalen。准确地说是过滤一些数据。
  • ItemRefItem 有什么区别?这些是完全相同的类吗?
  • 是的,一样。它们是相同的类,这是一个错字。
  • 你可以edit你的问题来修正错别字。

标签: java java-8 functional-programming


【解决方案1】:

我可能不会直接回答您关于如何改进第三种解决方案的问题,但我会建议使用 Streams 解决问题的不同方法。正如您在 cmets 中所说,您基本上想要展平递归数据结构(类似于树)并过滤掉一些数据。一种可能的方法是在Item 中创建一个方法,该方法返回所有元素的扁平流。 Item 内部的方法可能如下所示:

public Stream<Item> flattened() {
    return Stream.concat(
            Stream.of(this),
            items.stream().flatMap(Item::flattened));
}

请注意,我在这里使用了items 变量。我假设这是 getItem 方法返回的包含所有子项的变量的名称。

然后,您可以将该方法的结果用作常规 Stream 与树的所有元素。您可以像这样简单地过滤您想要的数据:

private static List<Item> getAdditemsFunctional(Item item) {
    return item.flattened()
        .filter(oi -> ADD_ACTION.equals(oi.getAction())
        .collect(Collectors.toList());
}

值得注意的是,我自己没有测试它,我不确定它是否会比你的解决方案更快。

【讨论】:

    【解决方案2】:

    您可以通过删除不必要的 collect 调用并将所有内容保持为流直到结束来优化此功能:

    private static List<ItemRef> getAdditemsFunctional(ItemRef po) {
        return getitemsFunctionalRec(po)
                .collect(Collectors.toList());
    }
    
    private static Stream<ItemRef> getitemsFunctionalRec(ItemRef oi) {
    
        Stream<ItemRef> result = oi
                .getItem()
                .stream()
                .flatMap(this::getitemsFunctionalRec);
    
        if (ADD_ACTION.equals(oi.getAction())) {
            result = Stream.concat(Stream.of(oi), result);
        }
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      相关资源
      最近更新 更多