本文转载自公众号“读芯术”(ID:AI_Discovery)

成都创新互联公司服务项目包括麻城网站建设、麻城网站制作、麻城网页制作以及麻城网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,麻城网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到麻城省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
循环语句是编程的基本组成部分。列表中的每一项都有用处,读取输入,直到输入结束,在屏幕上放置n个输入框。每当看到PR中的代码添加了循环语句,我都怒不可遏。现在我必定仔细检查代码,确保循环可以终止。
我希望所有运行良好的语句库中都看不到循环语句的踪影,但仍然有一些悄悄混进来,所以我想告诉大家如何消除循环语句。
让循环语句终结的关键是函数式编程。只需提供要在循环中执行的代码以及循环的参数(需要循环的内容)即可。我用Java作示范语言,但其实许多语言都支持这种类型的函数式编程,这种编程可以消除代码中的循环。
最简单的情况是对列表中的每个元素执行操作。
- List
 list = List.of(1, 2, 3); - // bare for loop.
 - for(int i : list) {
 - System.out.println("int = "+ i);
 - }// controlled for each
 - list.forEach(i -> System.out.println("int = " + i));
 
在这种最简单的情况下,无论哪种方法都没有太大优势。但第二种方法可以不使用bare for循环,而且语法更简洁。
我觉得forEach语句也有问题,应该只应用于副作用安全的方法。我所说的安全副作用是指不改变程序状态。上例只是记录日志,因此使用无碍。其他有关安全副作用的示例是写入文件、数据库或消息队列。
不安全的副作用会更改程序状态。下面为示例及其解决方法:
- // bad side-effect, the loop alters sum
 - int sum = 0;
 - for(int i : list) {
 - sum += i;
 - }
 - System.out.println("sum = " + sum);// no side-effect, sum iscalculated by loop
 - sum = list
 - .stream()
 - .mapToInt(i -> i)
 - .sum();
 - System.out.println("sum = " + sum);
 
另一个常见的例子:
- // bad side-effect, the loop alters list2
 - List
 list2 = new ArrayList<>(); - for(int i : list) {
 - list2.add(i);
 - }
 - list2.forEach(i -> System.out.println("int = " + i));// no sideeffect, the second list is built by the loop
 - list2 = list
 - .stream()
 - .collect(Collectors.toList());
 - list2.forEach(i -> System.out.println("int = " + i));
 
当你需要处理列表项方法中的索引时就会出现问题,但可以解决,如下:
- // bare for loop with index:
 - for(int i = 0; i < list.size(); i++) {
 - System.out.println("item atindex "
 - + i
 - + " = "
 - + list.get(i));
 - }// controlled loop with index:
 - IntStream.range(0, list.size())
 - .forEach(i ->System.out.println("item at index "
 - + i
 - + " = "
 - + list.get(i)));
 
老生常谈的问题:读取文件中的每一行直到文件读取完毕如何解决?
- BufferedReader reader = new BufferedReader(
 - new InputStreamReader(
 - LoopElimination.class.getResourceAsStream("/testfile.txt")));
 - // while loop with clumsy looking syntax
 - String line;
 - while((line = reader.readLine()) != null) {
 - System.out.println(line);
 - }reader = new BufferedReader(
 - new InputStreamReader(
 - LoopElimination.class.getResourceAsStream("/testfile.txt")));
 - // less clumsy syntax
 - reader.lines()
 - .forEach(l ->System.out.println(l));
 
应对上述情况有一个非常简便的lines方法,可以返回Stream类型。但是如果一个字符一个字符地读取呢?InputStream类没有返回Stream 的方法。我们必须创建自己的Stream:
- InputStream is =
 - LoopElimination.class.getResourceAsStream("/testfile.txt");
 - // while loop with clumsy looking syntax
 - int c;
 - while((c = is.read()) != -1) {
 - System.out.print((char)c);
 - }
 - // But this is even uglier
 - InputStream nis =
 - LoopElimination.class.getResourceAsStream("/testfile.txt");
 - // Exception handling makes functional programming ugly
 - Stream.generate(() -> {
 - try {
 - return nis.read();
 - } catch (IOException ex) {
 - throw new RuntimeException("Errorreading from file", ex);
 - }
 - })
 - .takeWhile(ch -> ch != -1)
 - .forEach(ch ->System.out.print((char)(int)ch));
 
这种情况下while循环看起来更好。此外,Stream版本还使用了可以返回无限项目流的 generate函数,因此必须进一步检查以确保生成过程终止,这是由于takeWhile方法的存在。
InputStream类存在问题,因为缺少peek 方法来创建可轻松转换为Stream的Iterator。它还会抛出一个检查过的异常,这样函数式编程就会杂乱无章。在这种情况下可以使用while语句让PR通过。
为了使上述问题更简洁,可以创建一个新的IterableInputStream类型,如下:
- static class InputStreamIterable implements Iterable
 { - private final InputStream is;
 - public InputStreamIterable(InputStreamis) {
 - this.is = is;
 - }
 - public Iterator
 iterator() { - return newIterator
 () { - public boolean hasNext() {
 - try {
 - // poor man's peek:
 - is.mark(1);
 - boolean ret = is.read() !=-1;
 - is.reset();
 - return ret;
 - } catch (IOException ex) {
 - throw new RuntimeException(
 - "Error readinginput stream", ex);
 - }
 - }
 - public Character next() {
 - try {
 - return (char)is.read();
 - } catch (IOException ex) {
 - throw new RuntimeException(
 - "Error readinginput stream", ex);
 - }
 - }
 - };
 - }
 - }
 
这样就大大简化了循环问题:
- // use a predefined inputstream iterator:
 - InputStreamIterable it = new InputStreamIterable(
 - LoopElimination.class.getResourceAsStream("/testfile.txt"));
 - StreamSupport.stream(it.spliterator(), false)
 - .forEach(ch -> System.out.print(ch));
 
如果你经常遇到此类while循环,那么你可以创建并使用一个专门的Iterable类。但如果只用一次,就不必大费周章,这只是新旧Java不兼容的一个例子。
所以,下次你在代码中写for 语句或 while语句的时候,可以停下来思考一下如何用forEach 或 Stream更好地完成你的代码。
                网页标题:For循环和While循环之流的终结
                
                转载来源:http://www.csdahua.cn/qtweb/news26/532576.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网