百科问答小站 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表达式是否比匿名内部类具有更好的可读性? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 
  「Lambda calculus」翻译为「Lambda 表达式」是否妥当? 
  C#的Lambda表达式是动态生成的吗? 
  Java 8的新特性lambda表达式是否比匿名内部类具有更好的可读性? 
  C#的Lambda表达式是动态生成的吗? 

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





© 2024-06-02 - tinynew.org. All Rights Reserved.
© 2024-06-02 - tinynew.org. 保留所有权利