百科问答小站 logo
百科问答小站 font logo



Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 第1页

  

user avatar   rednaxelafx 网友的相关建议: 
      

题主问的是“lambda表达式”与“匿名内部类”相比,那当然是大大改善了可读性。

在Java语言层面还没有lambda表达式的时代,经过FP思想开化的程序员们早就开始用匿名内部类来做类似的事情了。但就是略别扭。

例如我以前在淘宝写Java代码经常会用google-collections / Guava,就看Guava官方文档的一段例子吧:

code.google.com/p/guava
       Multiset<Integer> lengths = HashMultiset.create(   FluentIterable.from(strings)     .filter(new Predicate<String>() {        public boolean apply(String string) {          return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);        }      })     .transform(new Function<String, Integer>() {        public Integer apply(String string) {          return string.length();        }      }));      

这就是用匿名内部类来当FP风格的回调用。

如果用Java 8的话,这段代码可以直译为:

       Multiset<Integer> lengths = HashMultiset.create(   FluentIterable.from(strings)     .filter(string -> CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string))     .transform(string -> string.length()));      

这好歹一眼就能看出来程序的意图是什么,而不会被匿名内部类的“类型一行、方法名一行,真正方法内容一行”的这种仪式给干扰到。

而完全融合进Java 8风格的API的话,上面代码会变成类似这样:

       Multiset<Integer> lengths =   strings.stream()     .filter(string -> CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string))     .map(string -> string.length())     .toHashMultiSet();     

整个代码顺序就跟数据流动的顺序一致,意图也就更明确了。

至于这种适用lambda表达式 / 匿名内部类的风格的API好不好,那是另一个问题。

而lambda表达式会隐藏类型这点,不喜欢的话可以自己把类型全部写上去;lambda表达式的类型推导只是给了Java程序员一个选择,萝卜青菜反正自己挑。

前面

@戴威

的回答里的代码例子:

       File[] pics = folder.listFiles(   f ->      !f.isDirectory() &&      PICTURE_SUFFIX_LIST.stream().filter(       s ->          f.getName().toUpperCase().endsWith(s)).count() > 0);      

其实重新格式化并适用更合适的API来写的话,可以是:

       // File[] pics = folder.listFiles(   file -> !file.isDirectory() &&           PICTURE_SUFFIX_LIST.stream()           .anyMatch(suffix -> file.getName().toUpperCase().endsWith(suffix)) );     

至少对我来说它的意图非常明确,比人肉循环filter好多了。


user avatar   Ivony 网友的相关建议: 
      

可读性主要取决于写代码的人,而非语言特性。

就拿上面的例子来说:

       File[] pics = folder.listFiles(   f ->      !f.isDirectory() &&      PICTURE_SUFFIX_LIST.stream().filter(       s ->          f.getName().toUpperCase().endsWith(s)).count() > 0);      

我对这里面出现的Java的库函数一窍不通,但是我基本上还是能看明白这段代码在干什么。

唯一要费脑子的地方还是这段代码的缩进导致的问题,一般来说,我会写成这样:

       File[] pics = folder   .listFiles( f -> !f.isDirectory() &&      PICTURE_SUFFIX_LIST     .stream()     .filter( s -> f.getName().toUpperCase().endsWith(s) )     .count() > 0   );      

很明显这段代码的意图是非常清楚的

listFIles猜测为列出文件,f是文件,isDirectory是判断是否是目录,后面的stream.filter.count其实就是个Any。

所以意图就非常明确了,取出所有文件,这个文件不是目录,并且以PICTURE_SUFFIX_LIST里面某个字符串结尾。

RFX大大指出,Java也有anyMatch,所以这里可以进一步改写为:

       File[] pics = folder   .listFiles( f -> !f.isDirectory() &&      PICTURE_SUFFIX_LIST.stream()     .anyMatch( s -> f.getName().toUpperCase().endsWith(s) )   );      


事实上这段代码我在整理格式后已经用大脑直接转换成C#样式了:

       File[] pics = folder   .listFiles( f => f.IsDirectory == false &&      PICTURE_SUFFIX_LIST.Any( s => f.Name.EndsWith( s, StringComparision.IgnoreCaseOrdinal ) )    );      


而通常这种逻辑我会写成:

       var pics = from file in folder.EnumerateFiles()            where PictureFileExtensions.Contains( file.Extension )            select file;      

或者:

       var pics = folder.EnumerateFiles()            .Where( file => PictureFileExtensions.Contains( file.Extension );      



  

相关话题

  Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 
  Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 
  Java 8接口有default method后是不是可以放弃抽象类了? 
  用entity framework中查询时,是否有一种表达式最终无法翻译为sql语句? 
  Java 8接口有default method后是不是可以放弃抽象类了? 
  Java 8接口有default method后是不是可以放弃抽象类了? 
  Java 8接口有default method后是不是可以放弃抽象类了? 

前一个讨论
当一个人说自己“精通JavaScript, CSS3, HTML5”时应该如何理解?
下一个讨论
以下 CSS 栅格布局除了用 table 以外,有什么其他的方法吗?





© 2025-04-14 - tinynew.org. All Rights Reserved.
© 2025-04-14 - tinynew.org. 保留所有权利