《Java8 实战》-读书笔记第一章(02) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGLSL
V2EX    Java

《Java8 实战》-读书笔记第一章(02)

  •  
  •   NGLSL
    nglsl 2018-07-31 16:06:21 +08:00 1894 次点击
    这是一个创建于 2679 天前的主题,其中的信息可能已经有所发展或是发生改变。

    从方法传递到 Lamba

    接着上次的 Predicate,继续来了解一下,如果继续简化代码。

    把方法作为值来传递虽然很有用,但是要是有很多类似与 isHeavyApple 和 isGreenApple 这种可能只用一两次的方法定义一堆确实有点烦人。为了解决这个问题,Java8 它引入了一套新记法(匿名函数或 Lambda ),然你可以这样写:

    List<Apple> isRedApples = filterApples(FilteringApples.apples, apple -> "red".equals(apple.getColor())); 

    或者是:

    List<Apple> appleList = filterApples(FilteringApples.apples, apple -> apple.getWeight() < 120 && "red".equals(apple.getColor())); 

    甚至,你都可以不需要使用 filterApples 这个方法了,直接使用 Stream 中的 filter 方法就可以解决了:

    List<Apple> isGreenApple = apples.stream().filter(apple -> "green".equals(apple.getColor())) .collect(Collectors.toList()); 

    酷,看起来很不错。所以,你甚至都不需要为只用一次的方法写定义;这样的代码看起来更简洁、更清晰,因为你用不着去找自己到底传递了什么代码。

    在刚刚筛选苹果的过程中,就有使用到 Stream (流)其中的一个方法,这个 Stream 和 InputStream、OutputStream 是两个完全不同的东西。Stream 它是 Java8 中的一个核心新特,它是一套新的用来处理集合的 API,有很多类似与 filter 这样的方法而且使用起来非常的简单和简洁,可以简化大部分代码并且在并行的情况下利用多核 CPU,能很有效的提升对集合处理的性能。

    本章只是简单的介绍了一下流的使用方式,至于流的详细用法后面的章节会提到的。

    现在,有一串字符串,需要进行筛选并且转为大写以进行排序,在 Java8 之前是我们是这么干的:

    List<String> stringList = Arrays.asList("a1", "a2", "b1", "c1", "c2", "c4", "c3"); List<String> cList = new ArrayList<>(); for (String s : stringList) { // 筛选出以 c 开头的字符串 if (s.startsWith("c")) { // 将以 c 开头的字符串转为大写,添加到集合 cList.add(s.toUpperCase()); } } // 排序 Collections.sort(cList); // 遍历打印 for (String s : cList) { System.out.println(s); } 

    这样的代码看起来很头疼,需要写这么长一段的代码,在 Java8 中可以使用 Stream 进行优化:

    List<String> stringList = Arrays.asList("a1", "a2", "b1", "c1", "c2", "c4", "c3"); stringList.stream() // 筛选出以 c 开头的字符串 .filter(s -> s.startsWith("c")) // 将刚刚以 c 开头的字符串转为大写 .map(String::toUpperCase) // 排序 .sorted() // 循环遍历 .forEach(System.out::println); 

    太棒了,只需要短短的一行代码就可以完成!但是,使用 Stream 它也是有缺点的,它的性能不如 foreach 的效率高为了解决这个问题,Stream 支持并行。使用并行能极大的利用多核 CPU 的优势,例如说:这些代码原本只是用单核进行处理,现在有一台 8 核的 CPU 电脑,那么它的处理速度就会是单核的八倍。

    我们来进行比较一下,生成一个 0-100 的数字并写入到文件中,循序流 VS 并行流谁的效率更高.

    循序流:

    long startTime = System.currentTimeMillis(); OutputStream out = new FileOutputStream(new File("D:/integer1.txt")); IntStream.rangeClosed(0, 100) .forEach(i -> { try { Thread.sleep(100L); out.write(i); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }); long endTime = System.currentTimeMillis(); System.out.println("循序流:" + (endTime - startTime)); 

    并行流:

    long startTime = System.currentTimeMillis(); OutputStream out = new FileOutputStream(new File("D:/integer2.txt")); IntStream.rangeClosed(0, 100) .parallel().forEach(i -> { try { Thread.sleep(100L); out.write(i); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }); long endTime = System.currentTimeMillis(); System.out.println("并行流:" + (endTime - startTime)); 

    执行结果( I5-6200U 的笔记本上执行结果):

    循序流:10251 并行流:2620 

    效率明显比循序流要快很多嘛!但是,并行流并不是万能的,如果把 sleep 去掉后并且数字加到 100 万,你会发现运行的时间比循序流还要长。

    去掉 sleep 并且生成的数字是 0-100 万,所消耗的时间:

    循序流:2775 并行流:3346 

    至于为什么有时候并行流效率比循序流还低,这个以后的文章会解释。

    默认方法

    默认方法是 Java8 中的一个新特性,它的出现使得接口的升级变得平滑了,因为子类不是必须再去显示的实现接口中的方法了。

    例如:在 Java8 中,你可以直接调用 List 接口中的 sort 方法、它是用 Java8 List 接口中如下所示的默认方法实现的:

    default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } } 

    这意味着 List 的任何实体类都不需要显示的实现 sort,而在以前的 Java 版本中,除非提供了 sort 的实现,否则这些实体类都无法编译通过。但是,默认方法也存在着一些问题,一个类可以实现多个接口,那么好几个接口多有同样的默认方法,那么这是否意味着 Java 中有了某种形式的多继承?如果是多继承,那么会不会出现像 C++中菱形继承的问题?这些问题以后的文章中都会有解释和解决方案。

    第一章总结:

    1. 了解了 Java8 中的一些核心新特性,例如:Lambda 表达式、Stream、默认方法。
    2. 了解了 Lambda 表达式和 Stream 为代码带来的简洁性。
    3. 并行流带来的好处。
    4. Java8 中的默认方法带来的好处。

    代码案例:Github-chap1

    最近开通了微信公众号,欢迎大家关注:

    2 条回复    2018-08-07 08:55:02 +08:00
    OxO
        1
    OxO  
       2018-08-06 10:20:08 +08:00
    在看留名, 特此支持, 写的挺棒, 通俗易懂.
    NGLSL
        2
    NGLSL  
    OP
       2018-08-07 08:55:02 +08:00
    @OxO 谢谢!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     850 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 19:29 PVG 03:29 LAX 11:29 JFK 14:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86