Java Stream 在列表中迭代列表并计算布尔值

Java Stream Iterate list inside a list and calculate boolean value

如何计算list of list中的布尔值?列表中的每个元素都有一个嵌套列表。下面是代码片段

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;
}

ModelItemlist 个组件。组件 list 中的每个组件都有一个 notificationEnabled 标志。此外,每个组件都有一个 ChildComponent.

的列表 在以下情况下,

alertUser 应设置为 true

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

怎么做?

modelItem.components.stream().flatMap(a -> a.childComponents.stream()) 在检查时不起作用。片段中有更多详细信息

下面是示例代码:

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": []
        }
      ]
    }
  ]
}

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

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);

如果你把深度搜索放在正确的位置,一切都很容易。这里右边的class是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();
  }
}