一、介紹首先,看下map和flatMap的官方文檔說明 map

flatMap
 其實單純的看api說明還是比較抽象,下面我將以幾個實戰(zhàn)例子來幫助我們理解。然后再回過頭來看它的說明,就會有一種恍然大悟的感覺。
二、使用map示例
字母大小寫 public static void main(String[] args) throws Exception { // 將集合中的所有的小寫字母轉(zhuǎn)為大寫字母 List<String> list = new ArrayList<>(); list.add('hello'); list.add('world'); list.add('java'); list.add('python'); List<String> result = list.stream().map(String::toUpperCase).collect(Collectors.toList()); System.out.println(result); } 輸出結(jié)果如下: [HELLO, WORLD, JAVA, PYTHON]1 平方數(shù) public static void main(String[] args) throws Exception { // 求集合中每個元素的平方數(shù) List<Integer> nums = Arrays.asList(1, 2, 3, 4); List<Integer> result = nums.stream().map(n -> n * n).collect(Collectors.toList()); System.out.println(result); } 輸出結(jié)果如下: [1, 4, 9, 16]1 從上面例子可以看出,map 生成的是個 1:1 映射,每個輸入元素,都按照規(guī)則轉(zhuǎn)換成為另外一個元素。還有一些場景,是一對多映射關(guān)系的,這時需要 flatMap。 flatMap示例
單詞提取 public static void main(String[] args) throws Exception { // 將集合中的字符串中單詞提取出來,不考慮特殊字符 List<String> words = Arrays.asList('hello c++', 'hello java', 'hello python'); List<String> result = words.stream() // 將單詞按照空格切合,返回Stream<String[]>類型的數(shù)據(jù) .map(word -> word.split(' ')) // 將Stream<String[]>轉(zhuǎn)換為Stream<String> .flatMap(Arrays::stream) // 去重 .distinct() .collect(Collectors.toList()); System.out.println(result); } 輸出結(jié)果如下: [hello, c++, java, python]1 元素抽取 public class Main { public static void main(String[] args) throws Exception { // 初始化測試數(shù)據(jù) List<String> hobby1 = Arrays.asList('java', 'c', '音樂'); List<String> hobby2 = Arrays.asList('c++', 'c', '游戲'); User user1 = new User(1, '張三', hobby1); User user2 = new User(2, '李四', hobby2); ArrayList<User> users = new ArrayList<>(); users.add(user1); users.add(user2); // 將集合中每個用戶的愛好進行計算,取并集 List<String> result = users.stream() .map(user -> user.hobby) .flatMap(Collection::stream) .distinct() .collect(Collectors.toList()); System.out.println(result); } static class User { int id; String name; List<String> hobby; public User(int id, String name, List<String> hobby) { this.id = id; this.name = name; this.hobby = hobby; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return id == user.id && Objects.equals(name, user.name); } @Override public int hashCode() { return Objects.hash(id, name); } @Override public String toString() { return 'User{' + 'id=' + id + ', name='' + name + '\'' + '}'; } }} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
輸入結(jié)果如下: [java, c, 音樂, c++, 游戲]1 flatMap 把 input Stream 中的層級結(jié)構(gòu)扁平化,就是將最底層元素抽出來放到一起,最終 output 的新 Stream 里面已經(jīng)沒有 List 了,都是直接的數(shù)字. 三、map和flatMap的原理圖示map原理圖

對于Stream中包含的元素使用給定的轉(zhuǎn)換函數(shù)進行轉(zhuǎn)換操作,新生成的Stream只包含轉(zhuǎn)換生成的元素。這個方法有三個對于原始類型的變種方法,分別是:mapToInt,mapToLong和mapToDouble。這三個方法也比較好理解,比如mapToInt就是把原始Stream轉(zhuǎn)換成一個新的Stream,這個新生成的Stream中的元素都是int類型。之所以會有這樣三個變種方法,可以免除自動裝箱/拆箱的額外消耗。 flatMap原理圖

和map類似,不同的是其每個元素轉(zhuǎn)換得到的是Stream對象,會把子Stream中的元素壓縮到父集合中。
|