Java8 lambdas chap03

  • View
    380

  • Download
    3

Embed Size (px)

Text of Java8 lambdas chap03

  • Java 8 Lambdas

    3

    Streams

    (@ohtsuchi)

    1

  • 3

    External Iteration Internal Iteration

    Stream : lazy eager

    Stream : collect , map , filter ,flatMap,

    min(max) , reduce

    p3 Domain (Artist, Track, Album)

    2

  • From External Iteration to Internal Iteration (1)

    () Artist

    Example 3-1 for

    Example 3-2 iterator

    Example 3-3 stream

    Example 3-1 for

    boilerplate code

    parallel version

    nested

    int count = 0; for (Artist artist : allArtists) { if (artist.isFrom("London")) { count++; } }

    3

  • From External Iteration to Internal Iteration (2) Example 3-2 iterator -> External Iteration

    hasNext next

    Figure 3-1. External Iteration

    - operation

    int count = 0; Iterator iterator = allArtists.iterator(); while(iterator.hasNext()) { Artist artist = iterator.next(); if (artist.isFrom("London")) { count++; } }

    4

  • From External Iteration to Internal Iteration (3)

    Example 3-3 stream -> Internal Iteration

    Stream collection operation

    Figure 3-2. Internal Iteration

    long count = allArtists.stream() .filter( artist -> artist.isFrom("London") ) .count(); Stream

    (: true or false)

    5

  • From External Iteration to Internal Iteration (4)

    Example 3-3 2operation

    London artist

    artistlist

    2 operation Stream

    filter()

    test pass object

    test

    true or false

    count()

    Stream object

    6

  • Whats Actually Going On (1)

    Stream

    builder pattern

    -> build object

    operation 1 iterate

    Lazy ) filter

    : Stream builds up a Stream recipe

    eager

    ) count

    : void

    7

  • Whats Actually Going On (2) Example 3-4 Just the filter, no collect step

    Example 3-5 Just the filter, no collect step

    Example 3-6 Printing out artist names

    allArtists.stream() .filter( artist -> artist.isFrom("London") );

    allArtists.stream() .filter(artist -> { System.out.println(artist.getName()); return artist.isFrom("London"); });

    long count = allArtists.stream() .filter(artist -> { System.out.println(artist.getName()); return artist.isFrom("London"); }) .count();

    println

    println

    8

  • Common Stream Operations

    Stream :

    collect

    map

    filter

    flatMap

    min( max)

    reduce

    A Common Pattern Appears

    Putting Operations Together

    9

  • collect(toList())

    Stream List

    List collected = Stream.of("a", "b", "c") .collect(Collectors.toList()); assertEquals(Arrays.asList("a", "b", "c"), collected);

    10

    Stream

  • map (1)

    Stream

    Stream

    Example 3-8 : for

    List collected = new ArrayList(); for (String string : Arrays.asList("a", "b", "hello")) { String uppercaseString = string.toUpperCase(); collected.add(uppercaseString); }

    assertEquals(Arrays.asList("A", "B", "HELLO"), collected);

    11

  • map (2)

    Example 3-9 : map

    Figure 3-4. The Function interface

    1(T)1(R) Functionlamdamap

    (:String, :String )

    List collected = Stream.of("a", "b", "hello")

    .map(string -> string.toUpperCase())

    .collect(Collectors.toList());

    assertEquals(Arrays.asList("A", "B", "HELLO"), collected);

    12

  • filter Example 3-10 : for if

    Example 3-11 : Functional style filter

    if1function lamdafilter

    true OR false

    Figure 3-6. The Predicate interface

    List beginningWithNumbers = new ArrayList();

    for(String value : Arrays.asList("a", "1abc", "abc1")) { if ( Character.isDigit(value.charAt(0)) ) { beginningWithNumbers.add(value); } } assertEquals(Arrays.asList("1abc"), beginningWithNumbers);

    List beginningWithNumbers

    = Stream.of( "a", "1abc", "abc1" )

    .filter( value -> Character.isDigit(value.charAt(0)) )

    .collect( Collectors.toList() );

    assertEquals(Arrays.asList("1abc"), beginningWithNumbers);

    13

  • flatMap Stream

    Stream

    Example 3-12. Stream list

    map:

    Function

    map:

    Function (R) Stream

    List together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4) ) .flatMap(numbers -> numbers.stream())

    .collect(Collectors.toList());

    assertEquals(Arrays.asList(1, 2, 3, 4), together);

    (Map) a value -> a new value (flatMap) a value -> a new Stream

    List

    -> Stream

    (Collection#stream )

    14

  • max and min

    Example 3-13. : min

    min max

    Stream Comparator track.getLength

    java8 Comparator comparing static

    function

    : Function

    : Comparator

    min, max : Optional (-> )

    get

    List tracks = Arrays.asList(new Track("Bakai", 524), new Track("Violets for Your Furs", 378), new Track("Time Was", 451));

    Track shortestTrack = tracks.stream() .min( Comparator.comparing( track -> track.getLength() ) ) .get();

    assertEquals(tracks.get(1), shortestTrack);

    15

  • A Common Pattern Appears Example 3-14. : for (Example 3-13)

    (shortestTrack )

    for if

    If( currnetcurrent ) { }

    (shortestTrack )

    Example 3-15. The reduce pattern ()

    Ifcombine

    combine accumulator currnet

    Streams API operation

    Track shortestTrack = tracks.get(0); for (Track track : tracks) { if (track.getLength() < shortestTrack.getLength()) { shortestTrack = track; } }

    Object accumulator = initialValue; for(Object element : collection) { accumulator = combine(accumulator, element); }

    16

  • reduce (1)

    collection 1

    count, min, max, sum,

    Example 3-16. . reduce

    acc accumulator

    acc current -> acc

    int count = Stream.of(1, 2, 3)

    .reduce( 0, (acc, element) -> acc + element );

    assertEquals(6, count);

    T, T T BinaryOperator

    17

  • reduce (2)

    Example 3-18. . Imperative implementation

    int acc = 0;

    for (Integer element : Arrays.asList(1, 2, 3)) {

    acc = acc + element; }

    assertEquals(6, acc);

    18

  • Putting Operations Together

    Streamoperation

    () band

    "The" band

    band

    domain (Album) Stream

    List or Set OK List or Set (Collection) stream

    domain

    Stream better

    List or Set

    List or Set

    Set origins = album.getMusicians() .filter( artist -> artist.getName().startsWith("The") ) .map( artist -> artist.getNationality() ) .collect( Collectors.toSet() );

    : Stream (lazy)

    Artist -> String Stream

    19

  • Refactoring Legacy Code (Legacy code)

    forStream:

    step

    Legacy code : for

    step 1: Stream#forEach

    step 2: forEach

    step 3:

    step 4:

    () 1

    Example 3-19. Legacy code

    public Set findLongTracks(List albums) { Set trackNames = new HashSet(); for(Album album : albums) { for (Track track : album.getTrackList()) { if (track.getLength() > 60) { String name = track.getName(); trackNames.add(name); } } }

    return trackNames; } 20

  • Refactoring Legacy Code (step 1)

    Example 3-20. Refactor step 1: for Stream#forEach

    forEach

    3 (step 2) 3 Stream operation

    1 filter

    map

    Set step forEach

    public Set findLongTracks(List albums) {

    Set trackNames = new HashSet();

    albums.stream()

    .forEach( album -> { album.getTracks() .forEach( track -> { if (track.getLength() > 60) { String name = track.getName(); trackNames.add(name); } }); }); return trackNames; }

    21

  • Refactoring Legacy Code (step 2)

    Example 3-21. Refactor step 2: forEach

    album track stream (step3) flatMap

    public Set findLongTracks(List albums) {

    Set trackNames = new HashSet();

    albums.stream()

    .forEach(album -> { album.getTracks() .filter( track -> track.getLength() > 60 ) .map( track -> track.getName() ) .forEach( name -> trackNames.add(name) ); });

    return trackNames;

    }

    22

  • Refactoring Legacy Code (step 3)

    Example 3-22. Refactor step 3:

    Setnewelementadd

    (step 4) collect(toSet())

    trackNames

    public Set findLongTracks(List albums) {

    Set trackNam