【问题标题】:Java Stream Iterate list inside a list and calculate boolean valueJava Stream 在列表中迭代列表并计算布尔值
【发布时间】:2021-02-22 15:48:43
【问题描述】:

如何计算列表列表中的布尔值?列表中的每个元素都有一个嵌套列表。下面是代码sn-p

class ChildComponent {
    List<ChildComponent> childComponents = new ArrayList<>();
    Boolean notificationEnabled = Boolean.FALSE;
    String name;

    //respective Gettters/Setters
}

class ModelItem {
    List<ChildComponent> components = new ArrayList<>();
    Boolean alertUser;
}

ModelItem 有一个 list 的组件。组件list 中的每个组件都有一个notificationEnabled 标志。此外,每个组件都有一个ChildComponent 列表。

alertUser 在以下情况下应设置为true

  • 如果components 中的任何ChildComponentnotificationEnabled 设置为true
  • List&lt;ChildComponent&gt; childComponents 中的任何元素都将notificationEnabled 设置为true

所以,基本上,如果Components 中的任何一个将notificationEnabled 设置为true,那么alertUser 应该设置为true

怎么做?

modelItem.components.stream().flatMap(a -&gt; a.childComponents.stream()) 在检查时不起作用。更多细节在sn-p

下面是示例代码:

public static void main(String[] args) {

    ModelItem modelItem1 = new ModelItem();
    modelItem1.components.add(createC1());
    modelItem1.components.add(createC2());

    updateAlert(modelItem1);
}
        
**// does not work. It only check childComponents**
private static void updateAlert(ModelItem modelItem) {
    boolean anyMatchFilterPromptAtRun = modelItem.components.stream().flatMap(a -> a.childComponents.stream())
            .anyMatch(b -> b.notificationEnabled.equals(Boolean.TRUE));
    modelItem.alertUser = Boolean.valueOf(anyMatchFilterPromptAtRun);
}

private static ChildComponent createC1() {
    ChildComponent c1_1 = new ChildComponent();
    c1_1.name = "c1_1";
    c1_1.notificationEnabled = false;

    ChildComponent c1_2 = new ChildComponent();
    c1_2.name = "c1_2";
    c1_2.notificationEnabled = true;

    // main C2
    ChildComponent c1 = new ChildComponent();
    c1.name = "C1";
    c1.childComponents = Arrays.asList(c1_1, c1_2) ;
    c1.notificationEnabled = false;

    return c1;
}
    
private static ChildComponent createC2() {
    ChildComponent c1_1 = new ChildComponent();
    c1_1.name = "c1_1";
    c1_1.notificationEnabled = false;

    ChildComponent c1_2 = new ChildComponent();
    c1_2.name = "c1_2";
    c1_2.notificationEnabled = true;

    // main C1
    ChildComponent c1 = new ChildComponent();
    c1.name = "C1";
    c1.childComponents = Arrays.asList(c1_1, c1_2) ;
    c1.notificationEnabled = false;

    return c1;
}

下面是示例结构

{
  "components": [
    {
      "name": "C1",
      "notificationEnabled": false,
      "childComponents": [
        {
          "name": "c1_1",
          "notificationEnabled": false,
          "childComponents": []
        },
        {
          "name": "c1_2",
          "notificationEnabled": true,
          "childComponents": []
        }
      ]
    },
    {
      "name": "C1",
      "notificationEnabled": false,
      "childComponents": [
        {
          "name": "c1_1",
          "notificationEnabled": false,
          "childComponents": []
        },
        {
          "name": "c1_2",
          "notificationEnabled": true,
          "childComponents": []
        }
      ]
    }
  ]
}

【问题讨论】:

    标签: lambda collections java-8 java-stream


    【解决方案1】:

    听起来您需要递归遍历组件的层次结构。你可以这样做:

    Stream<ChildComponent> recursiveWalk(List<ChildComponent> list) {
        if (list.isEmpty())
            return Stream.empty();
        }
        
        return Stream.concat(list.stream(),
                             recursiveWalk(list.stream()
                                 .map(ChildComponent::childComponents)
                                 .flatMap(Collection::stream)
                                 .collect(toList())));
    }
    
    alertUser = recursiveWalk(components).anyMatch(ChildComponent::notificationEnabled);
    

    【讨论】:

      【解决方案2】:

      如果你把深度搜索放在正确的地方,一切都很容易。这里正确的类是 ChildComponent。

      public class ChildComponent {
      
        List<ChildComponent> childComponents = new ArrayList<>();
        String name;
        boolean notificationEnabled;
        /** Deep search */
        public boolean isNotificationEnabled() {
          return notificationEnabled || childComponents.stream()
              .filter(ChildComponent::isNotificationEnabled).findFirst().isPresent();
        }
      }
      

      【讨论】:

      • 不幸的是,我不能在 ChildComponent 中这样做:(
      猜你喜欢
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 2012-09-27
      • 1970-01-01
      • 2017-09-20
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多