Lambda表达式学习篇三(流-下)

一、重构遗留代码

  为了进一步解释如何重构一流代码,本节将距离说明如何将一段使用循环进行集合操作的代码,重构成基于Stream的操作。

  假定选取一组专辑,找出其中所有长度大于一分钟的曲目名称。下面是一个例子,首先初始化一个set对象,用来保存找到的曲目名称。然后使用for循环遍历所有专辑,每次循环中在使用一个for循环遍历每张专辑的每首曲目,检查其长度是否大于60秒,如果是,则将该曲目的名称加入set对象。

  例如:遗留代码:找出代码大于一分钟的曲目

 1 private static Set<String> findLongTracks(List<Album> albums)
 2     {
 3         Set<String> trackNames=new HasSet();
 4         for(Album album:albums)
 5         {
 6             for(Track track:album.getTrackList())
 7             {
 8                 if(track.getLength()>60)
 9                 {
10                     String name=track.getName();
11                     trackNames.add(name);
12                 }
13             }
14
15         }
16         return trackNames;
17     }

1、重构第一步

public Set<string> findLongTracks(List<Album> albums){  Set<String> trackNames=new HashSet<>();  albums.stream()      .forEach(album->{        album.getTracks()             .forEach(treack->{                if(track.getLength()>60)                  {                    string name =track.getName();                    trackNames.add(name);                  }  });});return trackNames;}

在本次重构中,虽然用了流,但是没有发挥它的作用。事实上,重构后的代码还不如原来代码。

因此,要继续重构我们就应该找突破口,其中最内层的foreach就是突破口。最内层的foreach方法有三个功用:找出长度大于一分钟的曲目,得到符合条件的曲目名称,将曲目名称加入集合Set。这就意味着需要三项Stream的操作:

①找出满足条件的曲目是filter功能;

②得到曲目名称是map功能;

③终结操作可使用foreach方法将曲目名称加入一个集合。

2、重构的第二步

public Set<String> findLongTreacks(List<Album> albums){  Set<String> trackNames=new HashSet<>();  albums.stream()      .forEach( album->{        album.getTracks()            .filter(track->track.getLength()>60)            .map(track->track.getName)            .forEach(name->trackNames.add(name));}      );}

虽然做了改进但是代码还是很冗长。

理想的操作,莫过于找到一种方法,将专辑转化一个曲目的stream。任何时候想转换或者替代代码,都该使用map操作。这里将使用比map更复杂的flatMap操作,把多个Stream合并成一个Stream并返回。将foreach方法替换成flatMap后。

3、重构代码的第三部

public Set<String> findLongTracks(List<Album> albums)
{
  Set<String> trackName=new HaashSet();
  albums.stream()
    .flatmap(album->album.getTracks())
    .filter(track->track.getLength()>60)
    .map(track->track.getName())
    .foreach(name->trackName.add(name));

return trackNames;
}

上面的代码中使用一组简洁的方法调用替换掉了两个嵌套的for循环,看起来清晰许多。但是我们还可以继续修改,继续替换到最后一个for循环。

4、重构代码

public Set<String> findLongTracks(List<Album> albums){
return   album.stream()
      .flatMao(album->album.getTracks())
     .filter(track->track.getLength()>60)
     .map(track->track.getName())
     .collect(toSet());
}

  

时间: 2024-11-05 22:45:48

Lambda表达式学习篇三(流-下)的相关文章

Lambda表达式学习篇二(流-上)

一.从外部迭代到内部迭代 使用for循环计算伦敦的艺术家人数: int count=0; for(Artist artist:allArtists){ if(artist.isFrom("London")){ count++; } } 每次迭代集合类时,都需要写较多样本代码. 调用iterator,产生一个新的Iterator对象,进而控制整个迭代过程,这就是外部迭代. int count=0; Iterator<Artist> iterator=allArtists.it

java lambda表达式学习笔记

lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射人先射马,擒贼先擒王.学习一个库要学习它的入口类.lambda的入口类是Stream,一看Stream中的函数就会发现Function,Predicate等lambda元素. 一.几个概念     函数式接口 Functional Interface,除了static和default类型的方法外,只有一个函数

WPF-MVVM模式学习笔记4——Lambda表达式学习

在学习MVVM的过程中,其中自定义了一个超类NotificationObject,如下 public abstract class NotificationObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void RaisePropertyChanged(string propertyName) { PropertyChang

java 8 中lambda表达式学习

转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-of-lambda-expressions-in-java8.html Lambda表达式的语法基本语法:(parameters) -> expression或(parameters) ->{ statements; } 下面是Java lambda表达式的简单例子: // 1. 不需要参数,返回值

C++11 lambda表达式学习

lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的lambda表达式自己的认识.这里有参考文档http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf 给出两个例子,可以看出lambda表达式的写法 [](int x, int y) { return x + y; } [](int x, int y) -> int {

[Java 8] (9) Lambda表达式对递归的优化(下) - 使用备忘录模式(Memoization Pattern) .

使用备忘录模式(Memoization Pattern)提高性能 这个模式说白了,就是将需要进行大量计算的结果缓存起来,然后在下次需要的时候直接取得就好了.因此,底层只需要使用一个Map就够了. 但是需要注意的是,只有一组参数对应得到的是同一个值时,该模式才有用武之地. 在很多算法中,典型的比如分治法,动态规划(Dynamic Programming)等算法中,这个模式运用的十分广泛. 以动态规划来说,动态规划在求最优解的过程中,会将原有任务分解成若干个子任务,而这些子任务势必还会将自身分解成更

Lambda表达式基础篇

一.简介 一个Lambda Expression(译为Lambda式) 就是一个包含若干表达式和语句的匿名函数.可以被用作创建委托对象或表达式树类型.Lambda 表达式对于编写 LINQ 查询表达式特别有用. 所有的Lambda式都使用操作符"=>",表示"goes to (转变为)".操作符左边部分是输入参数表,右边部分是表达式或语句块.接下来就看一下它的作用及用法. 二.何时用? 在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从F

[Java 8] Lambda表达式对递归的优化(下) - 使用备忘录模式(Memoization Pattern)

使用备忘录模式(Memoization Pattern)提高性能 这个模式说白了,就是将需要进行大量计算的结果缓存起来,然后在下次需要的时候直接取得就好了.因此,底层只需要使用一个Map就够了. 但是需要注意的是,只有一组参数对应得到的是同一个值时,该模式才有用武之地. 在很多算法中,典型的比如分治法,动态规划(Dynamic Programming)等算法中,这个模式运用的十分广泛. 以动态规划来说,动态规划在求最优解的过程中,会将原有任务分解成若干个子任务,而这些子任务势必还会将自身分解成更

lambda表达式学习笔记(1) -- 作为委托的lambda表达式

C#中的Lambda表达式就是C# 2中匿名方法的演变,因此从一个匿名函数开始一步步简化写法. 例子是获取一个string参数,然后返回一个int. 首先匿名方法的写法如下: Func<string, int> returnLength; returnLength = delegate (string text) { return text.Length; }; Console.Write(returnLength("Hello")); lambda表达式最冗长的形式是: