1. 程式人生 > 其它 >Java Stream 流式程式設計實戰演練

Java Stream 流式程式設計實戰演練

Java 8 新引入的流式程式設計 (Stream) 功能很強大,用的好可以大大簡化程式碼,提高效率。同時,大資料程式設計框架的原始碼以及業務程式碼大量使用了流式程式設計的思想。所以,這一塊必須熟練掌握。

但是,流式程式設計不是 "the silver bullet" ,有些場景使用可能 overkill ,讓程式碼不那麼易讀,而且打 log 或者 debug 的時候費勁。下面就舉 2 例。

例1

業務邏輯:寫一個函式,判斷 Student 的性別是男生還是女生。

  • 實現1:是比較老派的寫法,中規中矩。
  • 實現2:是流式程式設計的寫法。使用了 Optional + map + filter

廢話不多說,上程式碼:

實體類

public class Student {
    private String name;
    private Gender gender;

    public Student(String name, Gender gender) {
        this.name = name;
        this.gender = gender;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Gender getGender() {
        return gender;
    }
    public void setGender(Gender gender) {
        this.gender = gender;
    }
}

enum Gender {
    Boy, Girl
}

實現1

public static boolean isBoy(Student student) {
	if (student == null || student.getGender() == null) return false;

	if (student.getGender() == Gender.Boy){
		return true;
	} else {
		return false;
	}
}

實現2

public static boolean isGirl(Student student) {
	return Optional.ofNullable(student)
			.map(Student::getGender)
			.filter(gender -> gender == Gender.Girl).isPresent();
}

主函式

public static void main(String[] args) {

	Student s1 = new Student("Alice", Gender.Girl);
	Student s2 = new Student("Bob", Gender.Boy);

	System.out.println(s1.getName() + " is a girl: " + isGirl(s1));
	System.out.println(s2.getName() + " is a boy: " + isBoy(s2));

}

輸出

Alice is a girl: true
Bob is a boy: true

個人認為,這裡使用流式程式設計有一點點 overkill ,因為老派的實現方法已經足夠簡潔。

例2

業務邏輯:有一個 list ,裡面放了一堆 map ,而 map 裡面放的是鍵值對:【姓名-成績】。要求,把所有學生的名字收集起來,做成一個字串輸出。

  • 實現1:使用 for 迴圈的常規寫法。
  • 實現2:使用了 flatmap + collect
public static void main(String[] args) {

	// prep data
	List<Map<String, String>> scoreList = new ArrayList<>();
	Map<String, String> scoreGroup1 = new HashMap();
	scoreGroup1.put("Alice", "70");
	scoreGroup1.put("Bob", "90");
	Map<String, String> scoreGroup2 = new HashMap();
	scoreGroup2.put("Charles", "80");
	scoreList.add(scoreGroup1);
	scoreList.add(scoreGroup2);

	// process 1
	StringBuilder names1 = new StringBuilder();
	for (Map<String, String> map: scoreList) {
		Set<String> set = map.keySet();
		for(String key: set) {
			if (!names1.toString().isEmpty()){
				names1.append(", " + key);
			} else {
				names1.append(key);
			}
		}
	}
	System.out.println("Process 1 - Student names: " + names1.toString());

	// process 2
	String names2 = scoreList
			.stream()
			.flatMap(e -> e.keySet().stream())
			.collect(Collectors.joining(", "));
	System.out.println("Process 2 - Student names: " + names2);
}

輸出

Process 1 - Student names: Bob, Alice, Charles
Process 2 - Student names: Bob, Alice, Charles

這個例子中,使用 flatpmap 還是大大簡化了程式碼的。

總結

從個人角度出發,打鐵還需自身硬。有些流式程式設計的程式碼一開始看確實晦澀難懂,那我們就平時多用 Stream 練練手,寫的多了,自然就熟了。

  • 如果是一個 legacy 的專案,就儘量跟原來的 coding style 保持一致,這樣減少 bug 率。
  • 如果是一個新的或者大資料的專案,那就多用流式程式設計。

參考