Java Lambda for在两个for循环中中断
我正在尝试将Java8中的迭代代码块转换为函数式。功能方法无法在共享集中找到匹配的消息Java Lambda for在两个for循环中中断,java,collections,java-8,functional-programming,java-stream,Java,Collections,Java 8,Functional Programming,Java Stream,我正在尝试将Java8中的迭代代码块转换为函数式。功能方法无法在共享集中找到匹配的消息 List<Optional<Message>> allMessages = new ArrayList<>(); Set<Status> allStatuses = getAllStatuses(); //Iterative : Working Set<StatusMessage> set = new HashSet<>(STATUS
List<Optional<Message>> allMessages = new ArrayList<>();
Set<Status> allStatuses = getAllStatuses();
//Iterative : Working
Set<StatusMessage> set = new HashSet<>(STATUS_MESSAGE.values());
for (StatusMessage statusMessage : set) {
for (Status status : statusMessage.getStatusAndInfo().keySet()) {
Optional<Message> message = MessageBuilder.createMessage(allStatuses, status, this::createMessage);
if (message.isPresent()) {
allMessages.add(message);
break;
}
}
}
//Functional : Not working - Never adds anything to the
//map even when matching status is present
STATUS_MESSAGE.values().stream()
.distinct()
.map(statusMessage -> statusMessage.getStatusAndInfo().keySet())
.flatMap(Collection::stream)
.map(key -> MessageBuilder.createMessage(allStatuses, key, this::createMessage))
.anyMatch(allMessages::add);
此外,出于调试目的,我如何看到流的每个步骤都发生了什么?intellij中调试器中的堆栈在流中没有显示任何内容。这应该可以做到:
STATUS_MESSAGE.values().stream()
.distinct()
.forEach(statusMessage ->
statusMessage.getStatusAndInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.findFirst()
.ifPresent(allMessages::add)
);
更新 要使用
toList
而不是添加到列表中来构建结果列表,请执行以下操作:
List<Optional<Message>> allMessages = STATUS_MESSAGE.values().stream()
.distinct()
.flatMap(statusMessage ->
statusMessage.getStatusAndInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.limit(1)
)
.collect(Collectors.toList());
List allMessages=STATUS\u MESSAGE.values().stream()
.distinct()
.flatMap(状态消息->
statusMessage.getStatusAndInfo().keySet().stream()
.map(状态->MessageBuilder.createMessage(所有状态,状态,此::createMessage))
.filter(可选::isPresent)
.限额(1)
)
.collect(Collectors.toList());
这应该可以做到:
STATUS_MESSAGE.values().stream()
.distinct()
.forEach(statusMessage ->
statusMessage.getStatusAndInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.findFirst()
.ifPresent(allMessages::add)
);
更新 要使用
toList
而不是添加到列表中来构建结果列表,请执行以下操作:
List<Optional<Message>> allMessages = STATUS_MESSAGE.values().stream()
.distinct()
.flatMap(statusMessage ->
statusMessage.getStatusAndInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.limit(1)
)
.collect(Collectors.toList());
List allMessages=STATUS\u MESSAGE.values().stream()
.distinct()
.flatMap(状态消息->
statusMessage.getStatusAndInfo().keySet().stream()
.map(状态->MessageBuilder.createMessage(所有状态,状态,此::createMessage))
.filter(可选::isPresent)
.限额(1)
)
.collect(Collectors.toList());
这应该是一条注释,但太长了
似乎您的
MessageBuilder.createMessage
方法过于复杂
检查以下相同逻辑的简化和更可读版本:
if (allStatuses.contains(status)) {
System.out.println("Found : " + status.toString());
return creator.apply(status);
}
return Optional.empty();
这应该是一个评论,但是太长了
似乎您的
MessageBuilder.createMessage
方法过于复杂
检查以下相同逻辑的简化和更可读版本:
if (allStatuses.contains(status)) {
System.out.println("Found : " + status.toString());
return creator.apply(status);
}
return Optional.empty();
您不应该使用
forEach
进行累加操作,因此这应该更为惯用:
Function<StatusInfo, Optional<Message>> messageForStatus = statusInfo ->
statusInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.findFirst()
.orElse(Optional.empty());
allMessages = STATUS_MESSAGE.values().stream()
.distinct()
.map(StatusMessage::getStatusAndInfo)
.map(messageForStatus)
.filter(Optional::isPresent)
.collect(toList());
Function messageForStatus=statusInfo->
statusInfo().keySet().stream()
.map(状态->MessageBuilder.createMessage(所有状态,状态,此::createMessage))
.filter(可选::isPresent)
.findFirst()
.orElse(可选.empty());
allMessages=STATUS_MESSAGE.values().stream()
.distinct()
.map(StatusMessage::getStatusAndInfo)
.map(messageForStatus)
.filter(可选::isPresent)
.collect(toList());
作为一个旁注,你有太多的选择,你可能想考虑一些更早的解包,因为一个选择列表也可能只是当前值的列表。
不应该使用<代码>前缀来积累操作,所以这应该更习惯:Function<StatusInfo, Optional<Message>> messageForStatus = statusInfo ->
statusInfo().keySet().stream()
.map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))
.filter(Optional::isPresent)
.findFirst()
.orElse(Optional.empty());
allMessages = STATUS_MESSAGE.values().stream()
.distinct()
.map(StatusMessage::getStatusAndInfo)
.map(messageForStatus)
.filter(Optional::isPresent)
.collect(toList());
Function messageForStatus=statusInfo->
statusInfo().keySet().stream()
.map(状态->MessageBuilder.createMessage(所有状态,状态,此::createMessage))
.filter(可选::isPresent)
.findFirst()
.orElse(可选.empty());
allMessages=STATUS_MESSAGE.values().stream()
.distinct()
.map(StatusMessage::getStatusAndInfo)
.map(messageForStatus)
.filter(可选::isPresent)
.collect(toList());
作为一个旁注,您有太多的选择,您可能需要考虑提前解包,因为OpTIONS的列表也可能是当前值的列表。
<代码>任意匹配期望谓词并返回布尔值。你可能想要.filter()
然后只.collect
你说的“不工作”是什么意思?请详细说明.anyMatch(allMessages::add)代码>将在成功添加后立即停止,这将在第一次迭代时发生。改为使用findFirst
(如果顺序不相关,则使用findAny,然后写入allMessages=…stream()…flatMap()…filter(可选::isPresent).findFirst()或lse(emptyList())
@njzk2但是中断
仅用于内部循环,您仍应继续使用外部循环…然后重新运行内部循环。因此,每个外部循环最多一个项目.STATUS\u消息是一个映射。我使用的命名肯定可以改进。anyMatch
需要一个谓词并返回一个布尔值。您可能需要.filter()
,然后只需。collect
您所说的“不工作”是什么意思?请详细说明。anyMatch(allMessages::add);
将在成功添加后立即停止,这将在第一次迭代时发生。请改用findFirst
(如果顺序不相关,则使用findAny,然后写入allMessages=…stream()…flatMap()…filter(可选::isPresent).findFirst().orElse(emptyList())
@njzk2但是中断
仅用于内部循环,您仍应继续使用外部循环…然后重新运行内部循环。因此,每个外部循环最多一个项目.STATUS_消息是一张地图。我使用的命名肯定可以改进。我优化并移动了两个对象初始化,但从未意识到这有多简单。感谢@ETOI注释,我优化并移动了两个对象初始化,从未意识到这有多简单。感谢不应使用@etofeach注释将内容添加到列表中。这就是collect的用途(即使在这种情况下,它意味着在地图中要稍微复杂一些。)middle@njzk2添加了解决方案。很好地使用了limit
,我没有想到在这种情况下使用它。不应使用foreach将内容添加到列表中。这就是collect的用途(即使在这种情况下,它意味着在地图中要稍微复杂一些。)middle@njzk2添加了解决方案。很好地使用了限制
,我没有想到在这种情况下使用它