哪种方法可以对嵌套对象列表进行分叉?java 8 flatmap vs每个?

Ash*_*inK 1 java foreach java-8 java-stream

我有一个Terminal对象:

class Terminal{

    List<TerminalPeriodApplicability> periods= new ArrayList<>();
    //few other attributes

    //getters & setters

}

Run Code Online (Sandbox Code Playgroud)

TerminalPeriodApplicability 宾语:

class TerminalPeriodApplicability{

    String name;
    boolean isRequired;
    //getters & setters
}
Run Code Online (Sandbox Code Playgroud)

我想根据的值TerminalPeriodApplicabilityoptionalmandatory Set的名称分为两类isRequired

我尝试了两种方法。一个与两个forEach,另一个与flatMap

List<Terminal> terminals= getTerminals();
Set<String> mandatoryPeriods = new HashSet<>();
Set<String> optionalPeriods = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)

方法1

terminals.forEach(terminal -> terminal.getApplicablePeriods().forEach(period->{
    if(period.getIsRequired())
        mandatoryPeriods.add(period.name());
    else
        optionalPeriods.add(period.name());
}));
Run Code Online (Sandbox Code Playgroud)

方法二:

List<TerminalPeriodApplicability> applicablePeriods = terminals
                .stream()
                .flatMap(terminal -> terminal.getApplicablePeriods().stream())
                .collect(Collectors.toList());

applicablePeriods.forEach(period->{
    if(period.getIsRequired())
        mandatoryPeriods.add(period.name());
    else
        optionalPeriods.add(period.name());
});
Run Code Online (Sandbox Code Playgroud)

我想知道哪种方法在时间和空间复杂度方面更有效。还是有更好的解决方案来解决这个问题?

Era*_*ran 6

您可以在您的flatMap版本中使用其他终端操作- partitioningBy代替toList-并避免第二种操作forEach

Map<Boolean,List<TerminalPeriodApplicability>> periods = terminals
            .stream()
            .flatMap(terminal -> terminal.getApplicablePeriods().stream())
            .collect(Collectors.partitioningBy(TerminalPeriodApplicability::getIsRequired);
Run Code Online (Sandbox Code Playgroud)

要么

Map<Boolean,Set<TerminalPeriodApplicability>> periods = terminals
            .stream()
            .flatMap(terminal -> terminal.getApplicablePeriods().stream())
            .collect(Collectors.partitioningBy(TerminalPeriodApplicability::getIsRequired,
                                               Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)

更正:由于您希望两个Sets包含Strings而不是TerminalPeriodApplicability实例,因此应为:

Map<Boolean,Set<String>> periods = terminals
            .stream()
            .flatMap(terminal -> terminal.getApplicablePeriods().stream())
            .collect(Collectors.partitioningBy(TerminalPeriodApplicability::getIsRequired,
                                               Collectors.mapping(TerminalPeriodApplicability::name,
                                                                  Collectors.toSet()));
Run Code Online (Sandbox Code Playgroud)