java图片循环替换,是否可以将Java中的所有循环结构替换为基于流的结构?

我正在探索Java Stream API的可能性,以发现是否可以用基于流的结构替换所有基于循环的结构。

作为一个可能暗示实际上可行的假设的示例,请考虑以下因素:

是否可以使用Stream API像下面的String.split(String)调用那样将包含由空格分隔的单词的字符串拆分为字符串数组?

String[] tokens ="Peter Paul Mary".split("");

我知道以下事实:基于流的解决方案可以像下面这样使用String.split(String)方法:

Stream.of("Peter Paul Mary".split(""))

.collect(Collectors.toList());

或使用Pattern.splitAsStream(CharSequence)(其实现当然使用基于循环的方法),但是我正在寻找仅Stream的解决方案,其含义与此Haskell代码段类似:

words   :: String -> [String]

words s =  case dropWhile Char.isSpace s of

"" -> []

s' -> w : words s''

where (w, s'') = break Char.isSpace s'

我之所以这样问,是因为我仍然想知道,Stream API的引入是否会导致我们处理Java对象集合的方式的深刻变化,或者只是向它添加另一个选项,从而使维护更大的代码库变得更具挑战性,而不是从长远来看要简化此任务。

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

@Michael Isnt"我正在探索Java Stream API的可能性"的原因?

为什么我也想到了第一个问题?同样是Stream.of("Peter Paul Mary".split(",")),这意味着它将以逗号分隔而不是空格,并且您将不会得到任何输出。您必须使用Stream.of("Peter Paul Mary".split("s+"))

Pattern.compile(",") .splitAsStream(myString) .collect(Collectors.toList());?顺便说一句,此.map (elem -> new String(elem))是多余的。

您认为什么是Stream API的一部分?

@lexicore java.util.stream包中的所有内容……也许。

@Sweeper那么Collection.stream()不是Stream API的一部分吗?

自定义收集器仅适合Java-8流吗?

根据您"仅流"的确切含义,这是不可能的。而且至少流不适合您的工作。

我认为如果需要访问索引可能会变得困难。仅使用流如何实现矩阵乘法或冒泡排序?

到底为什么要用流拆分字符串证明所有循环构造都可以用流替换?

@Michael-没错,它什么都没有证明。它只是一个提示。在这方面,这个问题尚未得到回答。看到我的问题编辑。

@ Angle.Bracket它没有给出任何提示。从根本上来说,您的问题似乎是"流会取代for循环吗?"和GhostCats回答正确,答案很明确。

我不会提供证明,但是我希望所有循环都可以用某些(不可读的)流代码(在后台使用循环)替换。

一个明显的非答案是:您问的是错误的问题!

是否可以将所有"与循环相关"的Java代码行都转换为简单的东西都没关系。

因为:良好的编程能力是使人们能够轻松阅读和理解的代码编写能力。

因此,当有人提出一条规则,即"我们只使用此后的流来做所有事情"时,该规则会大大减少您编写代码时的选择。与其能够仔细决定"我应该使用流"还是"应该使用简单的老式循环结构",不如说是"如何使用流"?

从这个角度来看,您应该专注于提出适用于您开发团队中所有人员的"规则"。这可能意味着要强调使用流构造。但是您绝对要避免绝对主义,而让每个开发人员编写以"最易读"的方式实现给定要求的代码。如果可以,则可以。如果没有,请不要强迫人们这样做。

不仅如此:根据您的实际操作,使用流还会带来性能成本。因此,即使您可以找到问题的流解决方案-您也必须了解其运行时成本。您肯定希望避免在流成本过高的地方使用流(尤其是当代码已经在性能的"关键路径"上时,例如:每秒成千上万次)。

最后:在一定程度上,这是一个技能问题。含义:当您接受了使用流的培训时,您很容易A)阅读别人编写的"流"代码,以及B)提出实际上易于阅读的"流"解决方案。换句话说:这又取决于您正在使用的上下文。前一周,我在教育另一个团队学习"纯净代码",而我的最后一个经历是"纯净代码,Java8流/ lambdas"。一个人问我"什么是溪流?"强迫这样的社区明天对流做任何事情都没有意义。

@Eugene A)评论太久了,B)没有答案。 令人惊讶的是,有时这些答案也是。

只是为了好玩(这是一种可怕的方式),我也不知道这是否满足您的需求:

List result =",,,abc,def".codePoints()

.boxed()

// .parallel()

.collect(Collector.of(

() -> {

List inner = new ArrayList<>();

inner.add(new StringBuilder());

return inner;

},

(List 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())

));

您的技术上正确的答案就像我提出不回答的理由;-)

被认为是对问题中提到的示例的正确答案。但是正如@Eugene自己写的那样,这肯定不是漂亮的代码。

但这并不能回答是否可以用基于流的结构替换Java中的所有循环结构的问题。它甚至不是将循环转换为流结构的示例,尽管这是由于问题的例子不多所致,因为对String.split的调用根本不是循环结构。如果我们忽略现有的split方法,则会迭代一个合理的循环解决方案,直到String.indexOf返回-1为止,而根本不符合该解决方案。

@Holger youre对,我想,我对Haskell不太了解,这对这里有帮助(我在编辑之前回答了,或者没有注意到它):(

@Holger进行澄清:我所举的示例旨在指向String.split(String)或Pattern.splitAsStream(CharSequence)的实现:这两个都是通过经典循环实现的。通过要求读者考虑仅使用Stream API拆分字符串的解决方案,我希望能找到有关我的更一般问题的提示。在这方面,@ Eugenes答案肯定对我有所帮助,因为它证明了至少在此特定情况下可以使用Stream API,这就是为什么我接受它。

@ Angle.Bracket,但是还有很多其他可能性可以通过流来实现。由于已经存在Pattern.splitAsStream(CharSequence),其实现方式不比此答案的方法更"基于循环",因此尚不清楚此答案给您带来什么...

@Holger看一下Pattern.splitAsStream(CharSequence)的(OpenJDK)实现:这是一个基于循环的实现,因此与答案方法大不相同。请注意,我不喜欢后者而不是前者-我只是好奇是否有可能。正如我在问题中所说的那样,我好奇的原因是:如果有可能,那么付出了什么代价。而且如果成本不是太高(我越来越怀疑),那么Java可能会变成类似于Haskell或F#之类的东西。

正如您在此处看到的,@ Angle.Bracket是使用Iterator实现的,就像CharSequence.chars一样,它是String继承的(在Java 8中)。当然,在两种情况下,Stream实现中都会有一个循环对其进行迭代。

@Eugene,为什么您使用boxed()和Collector.of(…)而不比IntStream的三参数collect(…)方法没有任何好处?当您进一步将List>替换为List时,解决方案的可怕程度将大大降低。

@Holger不使用StringBuilder是白痴,同意。但是3参数收集器确实有一个finisher方法,我需要...

您可以在三参数collect方法之后简单地链接.stream() .map(StringBuilder::toString) .collect(Collectors.toList())。此外,应将chars()替换为codePoints(),将.append(Character.toChars(character))替换为.appendCodePoint(character)。这样既干净又高效。

如果字符串具有任何结尾的定界符,则列表将比String.split更长。

@Michael确实如此,但这只是一个简单的filter ...已更正

@Eugene它不是那么简单。 String.split("a,,b")将给出长度为3的列表,您的长度为2的列表

每次我必须处理String / char时,@ Holger几天后,我才意识到我应该使用与code-pointsXXX相关的方法。您确实使它变得更好了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值