是否可以用基于流的构造替换Java中的所有循环构造?

是否可以用基于流的构造替换Java中的所有循环构造?,java,for-loop,java-8,java-stream,Java,For Loop,Java 8,Java Stream,我正在探索Java流API的可能性,以找出是否有可能用基于流的结构替换所有基于循环的结构。 作为一个例子,这可能暗示了这是可能的假设,考虑如下: 是否可以使用Stream API将包含由空格分隔的单词的字符串拆分为字符串数组,如下面调用string.split(string)就可以了 String[]tokens=“彼得·保罗·玛丽”.split(“”) 我知道基于流的解决方案可以使用String.split(String)方法,如下所示: Stream.of("Peter Paul Mary"

我正在探索Java流API的可能性,以找出是否有可能用基于流的结构替换所有基于循环的结构。 作为一个例子,这可能暗示了这是可能的假设,考虑如下:

是否可以使用Stream API将包含由空格分隔的单词的字符串拆分为字符串数组,如下面调用
string.split(string)
就可以了

String[]tokens=“彼得·保罗·玛丽”.split(“”)

我知道基于流的解决方案可以使用
String.split(String)
方法,如下所示:

Stream.of("Peter Paul Mary".split(" "))
      .collect(Collectors.toList());
或者使用
Pattern.splitAsStream(CharSequence)
(其实现当然使用了基于循环的方法),但我正在寻找一种仅流的解决方案,这意味着类似于Haskell片段的内容:

words   :: String -> [String]
words s =  case dropWhile Char.isSpace s of
                  "" -> []
                  s' -> w : words s''
                        where (w, s'') = break Char.isSpace s'
我这样问是因为我仍然在想,流API的引入是否会导致我们在Java中处理对象集合的方式发生深刻的变化,或者只是向它添加另一个选项,从而使维护更大的代码库而不是从长远来看简化这项任务变得更具挑战性

编辑:虽然有一个公认的答案(见下文),但它只表明在这种特殊情况下是可能的。我仍然对问题中要求的一般情况的任何提示感兴趣。

只是为了好玩(这是一种可怕的方法),我也不知道这是否符合您的需要:

List<String> result = ",,,abc,def".codePoints()
            .boxed()
            // .parallel()
            .collect(Collector.of(
                    () -> {
                        List<StringBuilder> inner = new ArrayList<>();
                        inner.add(new StringBuilder());
                        return inner;
                    },
                    (List<StringBuilder> list, Integer character) -> {
                        StringBuilder last = list.get(list.size() - 1);
                        if (character == ',') {
                            list.add(new StringBuilder());
                        } else {
                            last.appendCodePoint(character);
                        }
                    },
                    (left, right) -> {
                        left.get(left.size() - 1).append(right.remove(0));
                        left.addAll(right);
                        return left;
                    },
                    list -> list.stream()
                            .map(StringBuilder::toString)
                            .filter(x -> !x.equals(""))
                            .collect(Collectors.toList())

    ));
List result=“,,abc,def.”代码点()
.boxed()
//.parallel()
收集(
() -> {
列表内部=新的ArrayList();
添加(新的StringBuilder());
返回内部;
},
(列表,整数字符)->{
StringBuilder last=list.get(list.size()-1);
如果(字符==','){
添加(新的StringBuilder());
}否则{
最后。追加码点(字符);
}
},
(左,右)->{
left.get(left.size()-1)、append(right.remove(0));
左。addAll(右);
左转;
},
list->list.stream()
.map(StringBuilder::toString)
.filter(x->!x.equals(“”)
.collect(收集器.toList())
));
这里有一个明显的非答案:你问错了问题

如果所有“与循环相关”的Java代码行都可以转换成流线型代码,这并不重要

因为:好的编程是编写人类可以轻松阅读和理解的代码的能力

因此,当有人提出一个规则,说“我们只使用从此处来的流进行我们所做的一切”,那么这个规则就大大减少了编写代码时的选择。与其仔细决定“我应该使用流”还是“我应该使用一个简单的老式循环构造”,不如说“我如何使用流”

从这个角度来看,您应该专注于制定适用于您的开发团队中所有人的“规则”。这可能意味着扩大流构造的使用。但您肯定希望避免绝对主义,让每个开发人员编写以“最可读”的方式实现给定需求的代码。如果这在溪流中是可能的,那就好了。如果没有,不要强迫别人去做

除此之外:根据您的具体操作,使用streams也会带来性能成本。因此,即使您可以找到问题的流解决方案,您也必须了解其运行时成本。您当然希望避免在流成本太高的地方使用流(特别是当代码已经在性能方面的“关键路径”上时,例如:每秒调用无数次)


最后:在某种程度上,这是一个技能问题。意思:当你在使用streams方面经过培训时,你会更容易地A)阅读别人编写的“streamish”代码,B)想出实际上易于阅读的“streamish”解决方案。换句话说:这同样取决于您工作的环境。前几周,我在教另一个团队“干净的代码”,我最后的陪衬是“干净的代码,Java8流/lambdas”。一个人问我“什么是流?”明天强迫这样一个社区对流做任何事情都没有意义。

@Michael不是“我正在探索Java流API的可能性”的原因吗?为什么第一个问题也出现在我脑海中?另外
Stream.of(“Peter Paul Mary”.split(“,”)
这意味着它将在逗号上分离,而不是在空格上,您将不会得到任何输出。您必须使用
Stream.of(“Peter Paul Mary.split(//s+”)
Pattern.compile(“,”).splitAsStream(myString.collector.toList())?顺便说一下,这个<代码> .map(ELME->新字符串(ELEM))是多余的。您认为流API的一部分是什么?我认为如果您需要访问索引,它会变得很困难。您将如何仅使用流实现矩阵乘法或冒泡排序?@Eugene A)评论太长,B)没有答案。令人惊讶的是,这些答案有时也会出现。你技术上正确的答案就像是我提出非答案的原因;-)被认为是问题中提到的例子的正确答案。但正如@Eugene自己写的,这肯定不是一个漂亮的代码。这并不能回答是否有可能替换所有l