顯示具有 [ Java 文章收集 ] 標籤的文章。 顯示所有文章
顯示具有 [ Java 文章收集 ] 標籤的文章。 顯示所有文章

2018年8月25日 星期六

[ Java 文章收集 ] Functional Programming for Java Developers 讀書摘要

Source From Here 
 

為何要FP? 
作者說雖然是因為 Concurrency 而學 FP,但是後來卻很享受這種 Paradigm Shift (典範轉移)。OO 被發明因為 GUI,後來人們發現可以用來應用在各種領域上。OO 和 FP 都是工具,各有優缺點,但是現在人們碰到所有問題都用 OO 去解,就像你手上有著搥子,在你眼中什麼都看起來像釘子。 FP 不代表比 OO 優越,畢竟 OO 的好處已經被證實且廣泛應用。而是目前時代不同了,OO 的缺點在某些領域已經到了不可忽視的地步,有些挑戰性的問題用 FP 解更為適合,例如: 

1. Concurrent 
以往我們總是讓最聰明的人去解 Concurrent 問題,小心地注意 Synchronized access to shared。因此絕大部分的開發者不需要煩惱。但是今日CPU多核,Concurrent 需求大增,FP 可以給你正確方式和更高階的 Concurrency 抽象機制來讓這件事更容易。 

2. Big data (大部分的程式只是資料處理問題) 
當你需要處理 terabytes 等級的資料時,你絕對承受不了 Object 的 overhead,你需要更有效率有最少 overhead 的資料結構跟演算法。ORM 在這問題上是無用的,任何轉換 Relational data 的抽象機制是無用的。FP 可以给你最少的 overhead 來操作這些原始資料,又可以做到 DRY 跟 Reuse 性。用 FP 直接處理原始資料,你不需要 OO 的 overhead。 

3. Modular 
OO 當初的願景包括 Reusable components,可以直接放到你的 app 中。但是成功的 Library, Framework 案例都是你必須 follow 他們的規則來走,很多 code 還是必須重寫。OO 不算是非常成功在 “Component assembly” 
OO 無限制的彈性破壞了 Reuse,因為如何跟一個物件互動的方式太多了。一個系統有好的限制反而比較 Modular,就像 PC 的成功在於 IBM 設計出 PC 架構。Web 的成功在於 HTTP 的簡單協定。 

FP 用標準的 List, map, set 來組織資料,FP 的 functions 避免 side effect。去除 dependencies 讓 function 可以在不同 contexts 都可以直接 resue。 

4. Work Faster and Faster 
今日對於可以快速 deliver 比精確地模型 domain 還重要,因為我們更看重快速修正的能力,一天可以 deployment 好幾次。OO 強調的 object model 能力似乎可以再三考慮了,FP 可以幫助我們有彈性變化的能力。 

5. Simplicity 
很多 OO 的複雜性和 middleware 都是不必要的。FP 返樸歸真更為簡潔。 

什麼是FP? 
不是有 function 的程式語言就叫做 functional programming language 唷? 最早的 FP 是 Lisp,也是目前第二老的高階程式語言了(Fortran 最老),ML family 包括 Caml, OCaml, F#。最 purity 則是 Haskell,近期有 Clojure, Scala 在 JVM 上。基本原則: 

1. 避免 Mutable State 
Mutable value 讓 multithreaded programming 變困難。如果可以 immutable,那就不需要 synchronization 了。另外,程式也更 correctness 正確,特別是在一個大型系統中一個非 locally 的 mutations,要找 bugs 時特別辛苦。Java 有提供 final,但是這保險卻不夠。因為 final 的 object 還是可以修改!! 例如容器中的元素。沒有 mutable value 之後,FP 提供了其他有效率的方式來操作容器。 

不過,還是有部分的 mutability 是無法避免的,例如IO。但是 FP 鼓勵我們思考 Mutable 的必要,將 Mutable 的部份包裝起來,程式其他部分就是 Immutable 安全的。這些需要 Mutable 的部份可以用 STM 或 Actor 來解決 Concurrency 問題。 

2. Function 是一級資料, Lambdas 和 Closures, Higher-Order Functions 
First-class value 表示可以當成變數(或參數)直接傳遞,方法也不能回傳一個 function,在 Java 中甚至連 class 都不是 first-class。在 Ruby 中 function 和 class 都是。 
(method 和 function 的語意有一點差別,前者多半指物件中的方法,後者則比較廣義,不一定綁在物件或類別上。

Callback method 的情景是最常需要傳遞 function 的地方,Java 用 anonymous inner class 來解決這個問題。不是不行,只是不同 library 的類別 (或介面) 和要覆寫的 method 命名都不同,每次都要查。如果程式語言支援統一用 function wrapper 就簡潔多了。這種 anonymous function 又叫作 lambda。closure 指的是可以在 function 指涉到外面的變數。在 Java 有限度支援,inner class 中只可以用外面被 final 的變數。 

Function 可以回傳 Function 的能力叫做 Higher-Order Functions,在 Java 中只能用 function wrapper 來做了。 

3. Side-Effect-Free Function 沒有副作用 
不像OO,FP的 function 不論在什麼 context,執行結果都相同。只要參數列相同,不論什麼情況結果都相同 (叫做 referential transparency)。 

4. Recursion 遞迴 
因為要避免 State (loop counter 就是 mutable 變數),所以用遞迴處理迴圈。不過,深度遞迴會造成 stack 過深的效能問題,因此 FP 語言多會支援 tail-call recursion 的能力能將運算自動轉成迴圈。可惜的是 Java 沒有這個能力。 

5. Lazy Evaluation 
要表示無窮數列,不可能全算出來,lazy evaluation 可以在要的時候再計算。lazy evaluation 可以幫助我們需要時才執行昂貴的操作。完全的 lazy evaluation 需要 referential transparency 才辦的到,也就是需要 side-effect-free function 和 immutable value。(只有最 Pure Functional 的 Haskell 預設所有 expressions 都是 lazy

6. Declarative 風格,而不是 Imperative 
OO 基本上也是 Imperative 風格,一行行告訴電腦特定的步驟: 
  1. # Declarative  
  2. def factorial  
  3.   if (n==1return 1  
  4.   else return n * factorial(n-1)  
  5. end  
  6.   
  7. # Imperative 有許多 mutation step  
  8. def factorial  
  9.   result = 1  
  10.   for (i = 2; i<=n; i++) {  
  11.     result *= i   
  12.   }  
  13.   return result  
  14. end  
Declarative 風格也跟 lazy evaluation 很合。跟 mutability 和 side-effect function 則不相容。 

無論偏好 static 或 dynamic typing, FP 對於 type design 也有一套看法,除了下一章提到的核心容器 type,還有一件事值得學習: 

immutable 表示變數初始一定要有值,也就表示不應該允許 null,null 也常常是 bug 源頭,例如忘記去 check null 的存在。在 Java 中 Null type 就是 任何 type 的 subtype。會需要 null 的存在,顯然是因為我們需要一個變數來表示 “Optionally” 可有可無,那麼何不明顯建立一個 type 處理,例如一個抽象介面 Option 以及它的實體化 subtype (final) Some 和 (final) None 表示一個有一個無。因此在需要 null 的場合,使用 Some 和 None 來包裝。Java 的 type-safe 會保證你不會忘記一定要處理 Option,看是 Some 或 None,這種作法保證了程式的可靠性。 

像 Option 介面只允許 Some 和 None 這兩個 final 不能再 subtype 的 type,叫做 Algebraic data type,可以從一種 type 安全變換成另一種 type (下一章會有例子)。跟一般我們設計介面的 abstract data type 不限制 subtype,強調 polymorphic behavior 的用法概念不同。

資料結構和演算法 
FP 偏好使用核心提供的容器 Lists、Maps、Trees、Sets,不像 OO 愛用物件包裹。根據上一章的FP原則,來實際看一些資料結構和演算法。FP提供了常見的資料結構和對應的 Combinator 操作。Linked list 也是一種 Algebraic Data Type,只有兩種 subtype: empty 和 non-empty。這跟 Java 的 List type 不一樣,Map 也是 abstract data type。作者用 Java 實作了 functional-style 的 List, Map. 

Combinator functions: 處理容器的基本三招: 1. filter 2. map 3.fold 很多其他操作都是基於此。這三招又叫作 Combinators,是最厲害的 reusable 建構演算法可以組合出複雜的運算。這三招也讓你不必一直用遞迴。 

因為是 immutable,所以變數需要改變時,就要不斷的 Copy 出新值才行。如果碰到大資料,對效能就有問題了。好在 FP 內部實作利用了 Structure sharing 的方式,用 tree 結構避免 full-copy 來有效率的處理。這種資料結構叫做 Persistent Data Structure。 

利用 DSL (DSL 可以用 OO 也可以用 FP 實作) 來包裝 FP 操作,只使用核心資料結構和 Combinators。不需要每樣東西都物件化,OO 操作是錯誤的抽象化層級。 

Function Concurrency 
很喜歡作者的這句話 “Multithreaded programming, requiring synchronized access to shared, mutable state, is the assembly language of concurrency”,每次看 OO 程式語言的 threading 章節都覺得 multithreaded 是神人才能寫的東西,實在太難了。 雖然 immutable 特性已經讓很多 synchronization 不需要了。但是 mutate state 還是有不可避免的時候,這時候可以利用更高抽象層級的 Actors 和 STM 來確保 thread-safe。 

Actors 透過 Actor 來做訊息傳遞,每個 Actor 有自己的 queue。實作最好的大概是 Erlang 了。 
有趣的是,最早的 Smalltalk 想法還比較像 Actor Model,關鍵是 messaging。 
1. 只有一個 actor 負責改變狀態,所以其他 code 想改變時,都必須通知唯一的 actor,從而避免 synchronization 問題。
2. 允許多個 actors 修改,會有一個特別的 semaphore message 代表安全。


Actors 風險是如果 scope 太大,會造成 bottleneck。 

Java 上目前有兩個好的實作:Akka 和 Functional Java。Actors 模型有許多地方都受 Erlang 成功的啟發,包括 Akka 用了 Bridge design pattern 來增加 robustness 和 error recovery 能力。 

STM 提供記憶體層級的 ACI (記憶體所以做不到 During,所以不是ACID)。STM 背後的原理是 value 本身還是 immutable 的,如果有改變值,則透過改變 references,加上 Persistent Data Structures 機制增加效率。STM 目前做最好的語言大概是 Clojure。Akka 也有 STM 的實作。關於 Actor 和 STM 的使用時機比喻,RubyConf 2011 的這場 Scaling Ruby with Actors, or How I Learned to Stop Worrying and Love Threads 演講我覺得還不錯。 

更好的 OO 
OO 編程基本上是 Imperative,而 FP 是 declarative。Imperative 看起來很忙又很多 mutation,容易出錯。mutable 物件不 thread-safe 而且不易掌控修改。讓物件 immutable,盡量 declarative。雖然有限制,但是保持所有 public 抽象層的 Pure,即使內在不 Pure。以 LSV 為例,在 OO 中因為繼承的自由跟彈性,很難保證符合,於是透過測試或設計模式來做。例如 Template patterns,但是 FP 的 higher-order functions 就可以做到了,細節在 function argument 再定義即可。 

有些人覺得 FP 是不是讓 OO 世界的設計模式無用,其實這是搞混了模式的精神跟實作。某些 GOF 的 pattern 其實根本就是 FP 內建的功能(Singleton, Composite, Command, Iterator 等),有些則可以被取代(Template Method –> higher-order functions)。FP 也有自己的模式,例如 Fold 用法和 Pattern matching。Monad 被用在 sequence expressions。Vistor pattern 的用途 (go inside the object) 則被 Pattern matching 取代。 

Pattern matching 蠻像 switch 的加強版,是一種好用的 modularity 工具,可以根據 type 做 data extraction,使用 Pattern matching 來實作新功能而不會污染本來的 type 

什麼是好 type 設計? OO modeling 沒錯,但是不精準的 OO code 時卻不無法保證 LSV 的 type 正確性。這就是 OO programming 的問題,domain concept 都在變,不如化作 key-value pairs。當然也有好的 domain concept 是不會變,例如錢,zip codes 等等. 作者認為任何放在 collection 裡的都不應該有專屬的 type,讓 filter, map, fold 主導。type wrapper 不值得花費開發。 

ORM 跟其他 OO middleware 都是無謂的複雜,用 filter, map, fold 轉換資料形式即可。Domain object 雖然容易了解,但是好處卻不總是值得。越少 code 就越 Agile (Play framework 的 Scala Anorm API 是個好例子)。

2017年11月2日 星期四

[ Java 文章收集 ] Composing functions using compose and andThen

Source From Here 
What is function composition? 
It all has to do with creating small reusable functions that you can combine to compose new functions. 

Now, how can we achieve this using compose and andThen? 
Let's first define two simple functions - times2 and squared
  1. Function times2 = e -> e * 2;  
  2. Function squared = e -> e * e;    
Next, let's combine them, using compose and andThen
  1. times2.compose(squared).apply(4);    
  2. // Returns 32 = (4^2) * 2  
  3.   
  4. times2.andThen(squared).apply(4);    
  5. // Returns 64 = (4*2)^2  
As you can see, the difference between compose and andThen is the order they execute the functions. While the compose function executes the caller last and the parameter first, the andThen executes the caller first and the parameter last. 

Let's start composing functions 
Let's create an example to see how we can use this approach to create small pieces of reusable code - then put them together in different ways. Consider the following. We have a list of articles and we need to filter the articles based on different requirements. Let's start by introducing two basic functions - byAuthor and byTag - that filter articles based on an author and a tag. 
  1. BiFunction, List
    > byAuthor =  
  2.     (name, articles) -> articles.stream()  
  3.         .filter(a -> a.getAuthor().equals(name))  
  4.         .collect(Collectors.toList());  
  5.   
  6. BiFunction, List
    > byTag =    
  7.     (tag, articles) -> articles.stream()  
  8.         .filter(a -> a.getTags().contains(tag))  
  9.         .collect(Collectors.toList());  
Both of these functions are BiFunctions - meaning they take two parameters. byAuthor takes the name of an author and the list of articles, returning a list of the articles written by the author requested; Same goes for byTag. It takes a tag and the list of articles, returning articles with the requested tag. 

Since BiFunction takes two arguments, it only offers the andThen function. You can't put the result of a function into a function that takes two arguments, hence the lack of the compose function. Moving on - let's also throw in a basic function that sorts a list of articles from newest to oldest and a function that returns the first article a list. 
  1. Function, List
    > sortByDate =    
  2.                 articles -> articles.stream()  
  3.                     .sorted((x, y) -> y.published().compareTo(x.published()))  
  4.                     .collect(Collectors.toList());  
  5.   
  6. Function, Optional
    > first =  a -> a.stream().findFirst();  
Now that we have our basic functions, let's see how we can use them to compose new functions. Let's start by composing a function that will return the article that was most recently published
  1. Function, Optional
    > newest = first.compose(sortByDate);  
Using the functions first and sortByDate that we created earlier, we're able to create a new function that will return the newest article in a given list. We can continue to mix these function in several ways to compose functions with new meanings without repeating code. Finding an author's newest masterpiece
  1. BiFunction, Optional
    > newestByAuthor =  byAuthor.andThen(newest);  
Or just order an author's articles. 
  1. BiFunction, List
    > byAuthorSorted =    
  2.     byAuthor.andThen(sortByDate);  

Or maybe you don't care about the author. You just want the newest article based on your favourite tag. 
  1. BiFunction, Optional
    > newestByTag =    
  2.     byTag.andThen(newest);  
The point I'm trying to make is that the Function interface and it's compose functions can make it easier and more intriguing to stay DRY by creating small building blocks that can be combined to fit your needs. There you go - a few simple ways to compose functions using compose and andThen. Give it a try as well!

2017年10月19日 星期四

[ Java 文章收集 ] An Introduction to Functional Programming in Java 8: Part 3 - Streams

Source From Here 
Preface 
In the last part, we’ve learned about the Optional type and how to use it correctly. Today, we will learn about Streams, which you use as an functional alternative of working with Collections. Some method were already seen when we used Optionals, so be sure to check out the part about Optionals. 

Where do we use Streams? 
You might ask what’s wrong with the current way to store multiple objects? Why shouldn’t you use Lists, Sets and so on anymore? I want to point out: Nothing is wrong with them. But when you want to work functional (what you hopefully want after the last parts of this blog), you should consider using them. The standard workflow is to convert your data structure into a Stream. Then you want to work on them in a functional manner and in the end, you transform them back into the data structure of your choice

And that’s the reason we will learn to transform the most common data structures into streams. 

Streams are a wonderful new way to work with data collections. They were introduced in Java 8. One of the many reasons you should use them is the Cascade pattern that Streams use. This basically means that almost every Stream method returns the Stream again, so you can continue to work with it. In the next sections, you will see how this works and that it makes the code nicer. 

Streams are also immutable. So every time you manipulate it, you create a new Stream. Another nice thing about them is that they respect the properties of fP. If you convert a Data Structure into a Stream and work on it, the original data structure won’t be changed. So no side effects here! 

How to Convert Data Structures into Streams 

Convert Multiple Objects into a Stream 
If you want to make a Stream out of some objects, you can use the method Stream.of()
  1. public void convertObjects() {  
  2.     Stream objectStream = Stream.of("Hello""World");  
  3. }  
Converting Collections (Lists, Sets, …) and Arrays 
Luckily, Oracle has thought through the implementation of Streams in Java 8. Every Class that implements java.util.Collection has a new method called stream() which converts the collection into a Stream. Also Arrays can be converted easily with Arrays.stream(array). It’s as easy as it get’s. 
  1. public void convertStuff() {  
  2.     String[] array = {"apple""banana"};  
  3.     Set emptySet = new HashSet<>();  
  4.     List emptyList = new LinkedList<>();  
  5.   
  6.     Stream arrayStream = Arrays.stream(array);  
  7.     Stream setStream = emptySet.stream();  
  8.     Stream listStream = emptyList.stream();  
  9. }  
However, normally you won’t store a Stream in an object. You just work with them and convert them back into your desired data structure. 

Working with Streams 
As I already said, Streams are the way to work with data structures functional. And now we will learn about the most common methods to use. As a side note: In the next sections, I will use T as the type of the objects in the Stream. 

Methods we already know 
You can use some methods we already heard about when we learned about Optionals also with Streams. 

map 
This works pretty straight forward. Instead of manipulating one item, which might be in the Optional, we manipulate all items in a stream. So if you have a function that squares a number, you can use map to use this function over multiple numbers without writing a new function for lists. 
  1. public void showMap() {  
  2.     Stream.of(123)  
  3.         .map(num -> num * num)  
  4.         .forEach(System.out::println); // 1 4 9  
  5. }  
flatMap 
Like with Optionals, we use flatMap to going e.g from a Stream> to Stream. If you want to know more about look into part 2. Here, we want to concat multiple Lists into one big List. 
  1. public void showFlatMapLists() {  
  2.     List numbers1 = Arrays.asList(123);  
  3.     List numbers2 = Arrays.asList(456);  
  4.   
  5.     Stream.of(numbers1, numbers2) //Stream>  
  6.         .flatMap(List::stream)  //Stream  
  7.         .forEach(System.out::println); // 1 2 3 4 5 6  
  8. }  
Common Stream methods 
forEach 
The forEach method is like the ifPresent method from Optionals, so you use it when you have side effects. As already shown, you use it to e.g. print all objects in a stream. forEach is one of the few Stream methods that doesn’t return the Stream, so you use it as the last method of a Stream and only once. You should be careful when using forEach, because it causes side effects which we don’t want to have. So think twice if you could replace it with another method without side effects
  1. public void showForEach() {  
  2.     Stream.of(0123)  
  3.         .forEach(System.out::println); // 0 1 2 3  
  4. }  
filter 
Filter is a really basic method. It takes a ‘test’ function that takes a value and returns boolean. So it test every object in the Stream. If it passes the test, it will stay in the Stream or otherwise, it will be taken out. This ‘test’ function has the type Function. In the JavaDoc, you will see that the test function really is of the type Predicate. But this is just a short form for every function that takes one parameter and returns a boolean. 
  1. public void showFilter() {  
  2.     Stream.of(0123)  
  3.         .filter(num -> num < 2)  
  4.         .forEach(System.out::println); // 0 1  
  5. }  
Functions that can make your life way easier when creating ‘test’ functions are Predicate.negate() and Objects.nonNull(). The first one basically negates the test. Every object which doesn’t pass the original test will pass the negated test and vice versa. The second one can be used as a method reference to get rid of every null object in the Stream. This will help you to prevent NullPointerExeptions when e.g. mapping functions. 
  1. public void negateFilter() {  
  2.     Predicate small = num -> num < 2;  
  3.   
  4.     Stream.of(0123)  
  5.         .filter(small.negate()) // Now every big number passes  
  6.         .forEach(System.out::println); // 2 3  
  7. }  
  8.   
  9. public void filterNull() {  
  10.     Stream.of(01null3)  
  11.         .filter(Objects::nonNull)  
  12.         .map(num -> num * 2// without filter, you would've got a NullPointerExeception  
  13.         .forEach(System.out::println); // 0 2 6  
  14. }  
collect 
As I already said, you want to transform your stream back into another data structure. And that is what you use collect for. And most of the times, you convert it into a List or a Set
  1. public void showCollect() {  
  2.     List filtered = Stream.of(0123)  
  3.         .filter(num -> num < 2)  
  4.         .collect(Collectors.toList());  
  5. }  
But you can use collect for much more. For example, you can join Strings. Therefore, you don’t have the nasty delimiter in the end of the string. 
  1. public void showJoining() {  
  2.     String sentence = Stream.of("Who""are""you?")  
  3.         .collect(Collectors.joining(" "));  
  4.   
  5.     System.out.println(sentence); // Who are you?  
  6. }  
Shortcuts 
These are methods which you could mostly emulate by using mapfilter and collect, but these shortcut method are meant to be used because they declutter your code. 

reduce 
Reduce is a very cool function. It takes a start parameter of type T and a Function of type BiFunction. If you have a BiFunction where all types are the same, BinaryOperator is a shortcut for that. 

It basically stores all objects in the stream to one object. You can concat all Strings into one String, sum all numbers and so on. There, your start parameters would be the empty String or zero. This function helps a lot to make your code more readable if you know how to use it. 
  1. public void showReduceSum() {  
  2.     Integer sum = Stream.of(123)  
  3.         .reduce(0, Integer::sum);  
  4.   
  5.     System.out.println(sum); // 6  
  6. }  
Now I will give a little bit more information how reduce works. Here, it sums the first number with the sum of the second and the sum of the third and start parameter. As you can see, this produces a long chain of functions. In the end, we have sum(1, sum(2, sum(3, 0))). And this will be computed from right to left, or from the inside out. This is also the reason we need a start parameter, because otherwise the chain would’nt have a point where it could end. 

sorted 
You can also use Streams to sort your data structure. The class type of the objects in the Stream doesn’t even have to implement Comperable, because you can write your own Comperable. This is basically a BiFunction, but Comperator is a shortcut for all BiFunctions that take 2 arguments of the same type and return an int. 

And this int, like in the compareTo() function, shows us if the first object is “smaller” than the second one (int < 0), is as big as the second (int == 0), or is bigger than the second one (int > 0). The sorted function of the Stream will interpret these ints and will sort the elements with the help of them. 
  1. public void showSort() {  
  2.     Stream.of(3240)  
  3.         .sorted((c1, c2) -> c1 - c2)  
  4.         .forEach(System.out::println); // 0 2 3 4  
  5. }  
Other Kinds of Streams 
There are also special types of Streams which only contains numbers. With these new Streams you also have a new set of methods. Here, I will introduce IntStream and Sum, but there are also LongStream, DoubleStream,… . You can read more about them in the JavaDoc. To convert a normal Stream into an IntStream, you have to use mapToInt. It does exactly the same as the normal map, but you get a IntStream back. Of course, you have to give the mapToInt function another function which will return an int. 

In the example, I will show you how to sum numbers without reduce, but with an IntStream
  1. public void sumWithIntStream() {  
  2.     Integer sum = Stream.of(0123)  
  3.         .mapToInt(num -> num)  
  4.         .sum();  
  5. }  
Use Streams for Tests 
Tests can also be used to test your methods. I will use the method anyMatch here, but countmax and so on can help you too. If something goes wrong in your program, use peek to log data. It’s like forEach, but also returns the stream. As always, look into the JavaDoc to find other cool methods. 

anyMatch is a little bit like filter, but it tells you if anything passes the filter. You can use this in assertTrue() tests, where you just want to look if at least one object has a specific property. In the next example, I will test if a specific name was stored in the DB. 
  1. @Test  
  2. public void testIfNameIsStored() {  
  3.     String testName = "Albert Einstein";  
  4.   
  5.     Datebase names = new Datebase();  
  6.     names.drop();  
  7.   
  8.     db.put(testName);  
  9.     assertTrue(db.getData()  
  10.         .stream()  
  11.         .anyMatch(name -> name.equals(testName)));  
  12. }  
Shortcuts of Shortcuts 
And after I showed you some shortcut methods, I want to tell you that there are many more. There are even shortcuts of shortcuts! One Example would be forEachOrdered, which combines forEach and sorted. If you are interested in other helpful methods, look into the JavaDoc. I’m sure you are prepared to understand it and find the methods that you need. Always remember: If your code looks ugly, there’s a better method to use ;). 

A Bigger Example 
In this example, we want to send a message to every user whose birthday’s today. 

The User Class 
A user is defined by their username and birthday. The birthdays will be in the format “day.month.year”, but we won’t do much checking for this in today’s example. 
  1. public class User {  
  2.   
  3.     private String username;  
  4.     private String birthday;  
  5.   
  6.     public User(String username, String birthday) {  
  7.         this.username = username;  
  8.         this.birthday = birthday;  
  9.     }  
  10.   
  11.     public String getUsername() {  
  12.         return username;  
  13.     }  
  14.   
  15.     public String getBirthday() {  
  16.         return birthday;  
  17.     }  
  18.   
  19. }  
To store all users, we will use a List here. In a real program, you might want to switch to a DB. 
  1. public class MainClass {  
  2.   
  3.     public static void main() {  
  4.         List users = new LinkedList<>();  
  5.   
  6.         User birthdayChild = new User("peter""20.02.1990");  
  7.         User otherUser = new User("kid""23.02.2008");  
  8.         User birthdayChild2 = new User("bruce""20.02.1980");  
  9.   
  10.         users.addAll(Arrays.asList(birthdayChild, otherUser, birthdayChild2));  
  11.   
  12.         greetAllBirthdayChildren(users);  
  13.     }  
  14.   
  15.     private static void greetAllBirthdayChildren(List users) {  
  16.         // Next Section  
  17.     }  
  18.   
  19. }  
The Greeting 
Now, we want to greet the birthday children. So first off, we have to filter out all Users whose birthday is today. After this, we have to message them. So let’s do this. I won’t implement sendMessage(String message, User receiver) here, but it just sends a message to a given user. 
  1. public static void greetAllBirthdayChildren(List users) {  
  2.     String today = "20.02"//Just to make the example easier. In production, you would use LocalDateTime or so.  
  3.     users.stream()  
  4.         .filter(user -> user.getBirthday().startsWith(today))  
  5.         .forEach(user -> sendMessage("Happy birthday, ".concat(user.getUsername()).concat("!"), user));  
  6. }  
  7.   
  8. private static void sendMessage(String message, User receiver) {  
  9.     //...  
  10. }  
And now we can send greetings to the users. How nice and easy was that?! 

Parallelism 
Streams can also be executed parallel. By default, every Stream isn’t parallel, but you can use .parallelStream() with Streams to make them parallel. Although it can be cool to use this to make your program faster, you should be careful with it. As shown on this Site, things like sorting can be messed up by parallelism. So be prepared to run into nasty bugs with parallel Streams, although it can make your program significantly faster. 

Conclusion 
We have learned a lot about Streams in Java. We learned how to convert a data structure into a Stream, how to work with a Stream and how to convert your Stream back into a data structure. I have introduced the most common methods and when you should use them. In the end, we tested our knowledge with a bigger example where we greeted all birthday children. 

Supplement 
Part 0 - Motivation 
Part 1 - Functions as Objects 
Part 2 - Optionals 
Part 3 - Streams 
Part 4 - Splitter

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...