Your SlideShare is downloading. ×
0
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Java8 stream
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Java8 stream

1,200

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,200
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
33
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  1. Java 8 Stream @kojilin 2014/3/29@TWJUG
  2. Stream •java.util.stream •Support functional-style operations on streams of elements
 int sum = 
 widgetList.stream()
 .filter(b -> b.color == RED)
 .mapToInt(b -> b.getWeight())
 .sum();
  3. External Iteration long sum = 0; for(int i = 0; i < N; ++i){ sum += i * i; }
  4. Internal Iteration long sum = LongStream .range(0, N) .map(i -> i * i) .sum();
  5. •為什麼需要 Stream ? •從外部迭代轉為內部迭代 •外部迭代需要注意要做什麼跟如何做 •內部迭代著重在要做什麼比如何做更多 •將行為資料化 •讓函式庫幫你更多的忙 •讓程式碼更簡潔好讀
  6. Stream •Stream 不是資料結構,沒有 存資料 •包裹在現有的資料結構之上 •透過內部迭代 •Multi-thread •Laziness •Stream 有 iterator 方法,但沒有實作 Iterable •所以不能寫 for (String item : stream)
  7. Stream 的種類 •Stream<T> •Primitive Streams •IntStream •DoubleStream •LongStream •彼此之間可以透過像 mapToInt, mapToDouble, mapToObj 等方式切換
  8. Stream 的使用方式 long sum = LongStream .range(0, N) .map(i -> i * i) .filter(i -> i % 2 == 0) .sum(); •建立 Stream
  9. Stream 的使用方式 long sum = LongStream .range(0, N) .map(i -> i * i) .filter(i -> i % 2 == 0) .sum(); •透過連續的 intermediate operation 操作
  10. Stream 的使用方式 long sum = LongStream .range(0, N) .map(i -> i * i) .filter(i -> i % 2 == 0) .sum(); •最後用 terminal operation 結束
  11. 如何取得 Stream? •Collection#stream() •Arrays.stream(Object[]) •Stream.of(Object[]) •IntStream.range(int, int) •BufferedReader#lines() •Stream#filter() •etc.

  12. Intermediate Operation •回傳 Stream,可以接下一個 operation •Lazy •直到遇到 terminal operation 的方法前不 會有效果
  13. •filter
 •map
 •flatMap
 
 •sorted stream.filter( p -> p > 20); stream.map( p -> p.name); stream.flatMap( p -> 
 p.cars.stream()); stream.sorted(p1, p2 -> 
 p1.name.compareTo(p2.name));
  14. •limit
 •distinct
 •skip stream.limit(5); stream.distinct(); stream.skip(5);
  15. Stateful & Stateless •Stateful 表示在操作元素時,除了當下的元 素外需要考慮其他狀態 •sorted, skip, limit •Stateless 表示在操作元素時,除了當下的元 素外不用考慮其他狀態 •filter, map
  16. Terminal Operation •不會回傳 stream,整個 stream 只能有一個 terminal operation 呼叫 •呼叫後才會開始走查 stream,最後產生並回 傳結果或是製造 side-effect •呼叫完 terminal operation 後 stream 會被 當作被使用完畢 •Stream -> (Intermediate)* -> Terminal
  17. •forEach
 •reduce
 •collect
 
 •count stream.forEach( p -> print(p)); stream.reduce( 0, (a, b) -> a + b); stream.collect(
 Collectors.toList()); stream.count();
  18. •toArray
 •max
 •sum ( Primitive Stream )
 •average ( Primitive Stream ) stream.toArray(String[]::new); stream.max(String::compareTo); intStream.sum(); intStream.average();
  19. Reduction •將元素組合成一個結果 •reduce, collect, sum, max, count intStream.sum(); numbers.stream().reduce(0, 
 (x,y) -> x + y);
  20. <U> U reduce( U identity, BiFunction<U, ? super T, U > accumulator, BinaryOperator<U> combiner); Stream<T>#reduce •accumulator 和 combiner 每次處理完元素 後,必須回傳新的值
  21. Integer result = stream.reduce(0, (sum, b) -> sum + b.getWeight(), Integer::sum); Stream<T>#reduce
  22. list.stream().reduce( new ArrayList<>(), (integers, o) -> { integers.add(o); return integers; }, (integers, integers2) -> { integers.addAll(integers2); return integers; }); ❌
  23. list.stream().reduce( new ArrayList<>(), (integers, o) -> { ArrayList<Integer> list = new ArrayList<>(integers); list.add(o); return list; }, (integers, integers2) -> { ArrayList<Integer> list = new ArrayList<>(integers); list.addAll(integers2); return list; }); △
  24. Mutable Reduction •將元素累加到 mutable 的容器中 •Stream#collect •和 reduce 不同,是改變已經存在的值
  25. <R> R collect( Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner); Stream<T>#collect •accumulator 和 combiner 都是 consumer
  26. ArrayList<String> asList = stringStream.collect( ArrayList::new, ArrayList::add, ArrayList::addAll); Stream<T>#collect
  27. <R> R collect( Collector<? super T,A,R> collector); Stream<T>#collect •Collector 並不是很容易實作
  28. •所以 Collectors 提供了許多預設的方法提供 常用的 Collector •toList, groupingBy, toSet, toMap, counting stream.collect(Collectors.toList()); stream.collect(Collectors
 .groupingBy(…)); strStream.collect(Collectors
 .join(","));
  29. ???
  30. ????
  31. ! List<Item> items = new ArrayList<>…; Map<String, List<Item>> result = 
 items.stream().collect(groupingBy(
 Item::getOwner)); ! >> {owner1=[i1, i2], owner2=[i3],…}
  32. ! List<Item> items = new ArrayList<>…; Map<String, Set<String>> result = 
 items.stream().collect(groupingBy(
 Item::getOwner,
 toSet()));
 
 >> {owner1=[i1], owner2=[i3], …}
  33. List<Item> items = new ArrayList<>…; Map<String, Set<String>> result = 
 items.stream().collect(groupingBy(
 Item::getOwner,
 mapping(Item::getName(),
 toSet()))); ! >> {owner1=[name1], owner2=[name2],…}
  34. Lazy Evaluation List<Integer> items = 
 Arrays.asList(1, 2, 3, 4); items.stream() .filter( i -> { sout("A"+i); i % 2 == 0; }) .map( i -> { sout("B"+i); return i; }) .map( i -> { sout("C"+i); return i; }); •不會印出東西
  35. Lazy Evaluation List<Integer> items = 
 Arrays.asList(1, 2, 3, 4); items.stream() .filter( i -> { sout("A"+i); i % 2 == 0; }) .map( i -> { sout("B"+i); return i; }) .map( i -> { sout("C"+i); return i; }) .collect(toList());
  36. Lazy Evaluation List<Integer> items = 
 Arrays.asList(1, 2, 3, 4); items.stream() .filter( i -> { sout("A"+i); i % 2 == 0; }) .map( i -> { sout("B"+i); return i; }) .map( i -> { sout("C"+i); return i; }) .collect(toList()); >> A1, A2, B2, C2, A3, A4, B4, C4
  37. Parallel List<Integer> items = 
 Arrays.asList(1, 2, 3, 4); items.parallelStream() .filter( i -> { sout("A"+i); return i % 2 == 0; }) .map( i -> { sout("B"+i); return i; }) .map( i -> { sout("C"+i); return i; }) .collect(toList()); >> A1, A3, A4, A2, B4, B2, C2, C4
  38. Short-circuit Operation •Intermediate operation •能將無限的輸入轉換成有限的 stream •limit long sum = IntStream .iterate(1, n -> n+1) .limit(10) .sum();
  39. Short-circuit Operation •Terminal operation •能將無限的輸入, 在有限時間內結束 •findFirst, anyMatch, allMatch long sum = IntStream .iterate(1, n -> n+1) .filter(i -> i > 100) .findFirst();
  40. Example 1 •找出第一個 age > 20 的 Student for (Student student : students) { if (student.age > 20) { return student; } } }
  41. Optional<Student> student = students.stream() .filter(s -> s.age > 20) .findFirst();
  42. Example 2 •尋找 age > 20,成績 > 90 的 10 位 Student 的 id
  43. List<String> result = …; for (Student student : students) { if (student.age > 20 && student.grade > 90) { result.add(student.id); if(result.size() >= 10){ break; } } }
  44. List<String> result = students.stream() .filter(student -> student.age > 20) .filter(student -> student.grade > 90) .limit(10) .map(student -> student.id) .collect(Collectors.toList());
  45. Example 3 •找出所有 Article 評論大於 20 的 Category,並依照名稱排序。
  46. List<Category> result = …; for (Category category : categories) { for (Article a : c.getArticles()) { if (a.getCommentCount() >= 20) { result.add(c); break; } } } Collections.sort(result, 
 Comparator.comparing(c -> c.getName()));
  47. categories.stream() .filter(c -> c.getArticles() .stream() .anyMatch(a -> a.getCommentCount() >= 20)) .sorted(Comparator.comparing(c -> c.getName())) .collect(Collectors.toList());
  48. Example 4 •將 Person 依照年齡分類到不同 List •Map<Integer, List< Person >>
  49. Map<Integer, List<Person>> result = …; for (Person person : people) { result.computeIfAbsent(person.age, t -> new ArrayList<>()) .add(person); }
  50. Map<Integer,List<Person>> peopleByAge = people.stream() .collect(groupingBy(Person::getAge));
  51. •Stream 走查很容易跟預期的不同,所以操作 過程要避免產生副作用 •順序,走了 些元素,是否並行 注意
  52. ArrayList<String> results = new 
 ArrayList<>(); stream.filter(…)
 .forEach(s -> results.add(s)); List<String>results = stream
 .filter(…)
 .collect(Collectors.toList()); Side Effects
  53. Set<Integer> seen = 
 Collections.synchronizedSet(
 new HashSet<>()); stream.parallel().map(e -> { 
 if (seen.add(e)) return 0; 
 else return e; 
 })... Stateless Behaviors
  54. List<String> source = ...; source.stream()
 .filter(s -> {
 source.add(...);
 return s.length() > 10; 
 })
 ... Non-inferences •走查過程中不該動到來源資料結構 •除非該資料結構是支援 concurrent 存取
  55. •使用 Stream 的方式和外部迭代差異不小 •很多方法只看參數型態很難理解,從方法和 變數名稱去理解使用方式 •只能多寫多習慣 •通常寫完後會有較佳的可讀性 最後

×