我上课
public class Step
{
boolean isActive;
String name;
}
我有一个类型为Steps的Collection。 目前没有使用流
StringBuilder stringBuilder = new StringBuilder();
for (Step step : steps)
{
List<String> nextStepNames = getNextStepNames(step);
List<String> conditions = getConditions(step);
for (int i = 0; i < nextStepNames.size(); i++)
{
stringBuilder.append("If ").append(step.getName()).append("is active, and condition (").append(conditions.get(i)).append(") is true, then move to ").append(nextStepNames.get(i)).append("\n");
}
}
如果我的步骤集合包含stepA,StepB和stepC, 这就是我的输出:
If stepA is active, and condition (c1A) is true, then move to step1A
If stepA is active, and condition (c2A) is true, then move to step2A
If stepA is active, and condition (c3A) is true, then move to step3A
If stepB is active, and condition (c1B) is true, then move to step1B
If stepB is active, and condition (c2B) is true, then move to step2B
If stepB is active, and condition (c3B) is true, then move to step3B
If stepC is active, and condition (c1C) is true, then move to step1C
If stepC is active, and condition (c2C) is true, then move to step2C
If stepC is active, and condition (c3C) is true, then move to step3C
nextStepNames
和conditions
列表的大小相同,并且列表中的索引彼此对应。
我无法将此代码转换为流。我不确定是否可能。
答案 0 :(得分:1)
Java缺乏以优雅的纯函数样式有效解决问题的能力。
但是,您可以尝试类似
str = steps.stream()
.map(step ->
IntStream
.range(0, getNextStepNames(step).size())
.mapToObj(i -> Stream.of(
"If ",
step.getName(),
" is active, and condition (",
getConditions(step).get(i),
") is true, then move to ",
getNextStepNames(step).get(i),
"\n"))
.flatMap(Function.identity())
)
.flatMap(Function.identity())
.collect(Collectors.joining());
由于getNextStepNames
和getConditions
的反复评估以及无法提前分配完整的输出缓冲区,因此效率很低。
当然,您可以尝试使用第三方库来减轻这种情况,但是恕我直言,这是不值得的。
您的解决方案效率更高,更易于理解和维护。您可以通过初始化StringBuilder
使其大小等于或略大于最终输出大小来进一步改善这一点。
答案 1 :(得分:0)
距离目标更近的一步可能是:
for (Step step : steps) {
List<String> nextStepNames = getNextStepNames(step);
List<String> conditions = getConditions(step);
IntStream.range(0, nextStepNames.size())
.forEach(i -> stringBuilder.append("If ")
.append(step.getName())
.append("is active, and condition (")
.append(conditions.get(i))
.append(") is true, then move to ")
.append(nextStepNames.get(i)).append("\n"));
}
答案 2 :(得分:0)
尝试一下:
String output = Arrays.stream(steps) // if it's an array or steps.stream() for a list
.flatMap(step -> IntStream.range(0, getNextStepNames(step).size())
.mapToObj(i -> String.format(
"If %s is active, and condition (%s) is true, then move to %s",
step.getName(),
getConditions(step).get(i),
getNextStepNames(step).get(i))))
.collect(Collectors.joining("\n"));
我们的初始流仅包含三个元素(步骤A,B和C),因此对于每个元素,我们需要另一个流。我们使用两个列表的所有有效索引创建一个IntStream。我们将它们映射到字符串,从这两种方法中获取元素。我使用了String.format
,但是当然可以用StringBuilder
或简单的字符串串联代替。
这时,流中有流。我们只需调用flatMap
就可以将其压平为单个流。
最后,我们可以使用\n
作为胶水来连接所有元素。
getNextStepNames
和getConditions
看上去似乎很相关,但是却是分开的,真是可惜。但这是另一个故事。