如何跳出foreach循环,java foreach用法

foreach的使用方法

太棒了! 正在将代码库迁移到Java8。 我们用函数替换所有内容。 放弃设计模式。 删除面向对象。 没错! 我们走吧!

等一下,Java 8问世一年多了,这种兴奋又回到了日常工作中。

baeldung.com从2015年5月开始实施的一项非代表性研究显示,38%的读者已经采用了Java 8。 迄今为止,Typsafe在2014年底进行的一项研究显示,在用户中,Java 8的采用率为27%。

这对代码库意味着什么? 某些Java 7- Java 8迁移重构是理所当然的。 例如,将Callable传递给ExecutorService。

executor services=.//Java7- meh . future stringf=s.submit (newcallablestring ) { @Override public String call ) } }; ); //Java 8 - of course! futurestringf=s.submit ((-' hello world ' ); 匿名类样式实际上没有在此添加值。

除了这些通俗易懂的话题以外,还有一些不太引人注目的话题。 例如,要使用外部迭代器还是内部迭代器? 另请参阅Neil Gafter在2007年发表的关于永恒主题的有趣读物。 http ://g after.blogspot.ch/2007/07/internal-versus-external-iterators.htts

以下两个逻辑的结果是相同的

listintegerlist=arrays.as list (1,2,3 ); //old school for (integeri : list ) System.out.println(i ) I; //' modern ' list.foreach (system.out :3360 println ); 我主张,应该密切关注“摩登”方法。 也就是说,只有在您真正受益于内部功能迭代的情况下(如链接流映射()、平面映射(flatMap )或其他操作中的一系列操作映射),才应该谨慎。

与经典方法相比,这是“现代”方法缺点的简短列表:

1 .表演你会因此失去Angelika Langer在她的文章和她在会议上发表的相关演讲中对这个主题的很好总结:

3359 jax enter.com/Java-performance-tutorial-how-fast-are-the-Java-8-streams-118830.html

在许多情况下,性能并不重要,因此不应该过早优化。 因此,可能会声称此参数本身不是真正的参数。 然而,在这种情况下,我反驳这种态度,因为与普通的for循环相比,(Stream.forEach ) )具有非常大的开销,所以缺省情况下即使使用它也很难在你的所有CPU上产生浪费的CPU周期APP 只根据循环模式的选择来说将CPU消耗量增加10%-20%,是根本错误的。 是的每个周期都不重要,但可以避免整个系统的负担。

这是Angelika正常周期的基准测试结果,在装箱的整数列表中发现了最大值:

ArrayList,for-loop : 6.55 msArrayList,seq. stream: 8.33 ms其他情况下,在对原始数据类型执行比较简单的计算时,绝对应该回到经典的for循环。 (希望是数组而不是集合)。

这是Angelika常规循环的基准结果,在原始整数数组中找到了最大值。

int-array、for-loop : 0.36 msint-array、seq. stream: 5.35 ms过早优化效果不佳,但避免过早优化的货物教育更差。 重要的是反思我们所处的环境,并在该环境中做出正确的决定。 我以前写过关于表演的博客,请参考这里的文章《Java十大简单性能优化》

2 .可读性至少对大多数人来说,我们是软件工程师。 我们总是讨论我们的代码样式。 好像它真的很重要一样。 例如,空格或大括号。

这是因为软件很难维护。 特别是别人写的代码。 很久以前。 在切换到Java之前,可能谁只写了c代码。

当然,到目前为止的例子中,没有可读性的问题。 这两个版本可能是同等的。

listintegerlist=arrays.as list (1,2,3 ); //old school for (integeri : list ) System.out.println(i ) I; //' modern ' list.foreach (system.out :3360 println ); 但是这里发生了什么?

List<Integer> list = Arrays.asList(1, 2, 3);// Old schoolfor (Integer i : list) for (int j = 0; j < i; j++) System.out.println(i * j);// "Modern"list.forEach(i -> { IntStream.range(0, i).forEach(j -> { System.out.println(i * j); });});

事情开始变得更加有趣和异常。 我不是说“更糟”。 这是实践和习惯的问题。 而且没有黑/白问题的答案。 但是,如果其余代码库是必须的(可能是这样),则嵌套范围声明和forEach()调用以及lambda肯定是dtdxf,这会在团队中引起认知冲突。

您可以构建一些示例,其中命令式方法比等效的功能式方法感觉更尴尬,如此处所示:

势在必行–功能分离pic.twitter.com/G2cC6iBkDJ

— Mario Fusco(@mariofusco) 2015年3月1日

但是在很多情况下,这是不正确的,并且要编写功能上相对简单的命令相当的命令相当困难(同样,效率低下)。 可以在此博客的先前文章中看到一个示例: http : //blog.jooq.org/2015/09/09/how-to-use-java-8-functional-programming-to-generate-an-alphabetic -顺序/

在那篇文章中,我们生成了一个字符序列:

A, B, ..., Z, AA, AB, ..., ZZ, AAA

…类似于MS Excel中的列:

命令式方法(最初由Stack Overflow上的一个未命名用户使用):

import static java.lang.Math.*; private static String getString(int n) { char[] buf = new char[(int) floor(log(25 * (n + 1)) / log(26))]; for (int i = buf.length - 1; i >= 0; i--) { n--; buf[i] = (char) ('A' + n % 26); n /= 26; } return new String(buf);}

……在简洁性上可能胜过功能性的:

import java.util.List; import org.jooq.lambda.Seq; public class Test { public static void main(String[] args) { int max = 3; List<String> alphabet = Seq .rangeClosed('A', 'Z') .map(Object::toString) .toList(); Seq.rangeClosed(1, max) .flatMap(length -> Seq.rangeClosed(1, length - 1) .foldLeft(Seq.seq(alphabet), (s, i) -> s.crossJoin(Seq.seq(alphabet)) .map(t -> t.v1 + t.v2))) .forEach(System.out::println); }}

并且这已经在使用yjfdxfλ ,以简化功能Java的编写。

3.可维护性

让我们再次考虑前面的示例。 现在,我们不再对值相乘,而是对它们进行除法。

List<Integer> list = Arrays.asList(1, 2, 3);// Old schoolfor (Integer i : list) for (int j = 0; j < i; j++) System.out.println(i / j);// "Modern"list.forEach(i -> { IntStream.range(0, i).forEach(j -> { System.out.println(i / j); });});

显然,这是自找麻烦,我们可以在异常堆栈跟踪中立即看到问题。

老套

Exception in thread "main" java.lang.ArithmeticException: / by zeroat Test.main(Test.java:13)

现代

Exception in thread "main" java.lang.ArithmeticException: / by zeroat Test.lambda$1(Test.java:18)at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)at java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:557)at Test.lambda$0(Test.java:17)at java.util.Arrays$ArrayList.forEach(Arrays.java:3880)at Test.main(Test.java:16)

哇。 我们只是…吗? 是。 这就是为什么我们首先在项目1中遇到性能问题的原因。 对于JVM和库,内部迭代只是要做很多工作。 这是一个非常简单的用例,我们可以用AA, AB, .., ZZ系列的产品展示同样的东西。

从维护的角度来看,函数式编程风格比命令式编程要困难得多,尤其是当您在传统代码中盲目地将两种风格混合在一起时。

结论

这通常是一个关于函数式编程,关于声明式编程的博客。 我们喜欢lambda。 我们喜欢SQL。 结合起来,它们可以创造奇迹。

但是,当您迁移到Java 8并打算在代码中使用更多功能的样式时,请注意FP并不总是总会更好-出于各种原因。 实际上,它从来没有“更好”,它只是不同而已,它使我们对问题有不同的推理。

我们的Java开发人员将需要进行练习,并对何时使用FP以及何时坚持使用OO /命令式有一个直观的了解。 通过适当的实践,将两者结合起来将有助于我们改善软件。

或者,用鲍伯叔叔的话来说:

底线就是这个。 当您知道OO编程是什么时,它就是好的。 当您知道函数式编程是什么时,它就是好的。 一旦了解了功能性OO编程,它也是不错的选择。

http://blog.cleancoder.com/uncle-bob/2014/11/24/FPvsOO.html

翻译自: https://www.javacodegeeks.com/2015/12/3-reasons-shouldnt-replace-loops-stream-foreach.html

foreach用法

网友留言(0条)

发表评论