天天看點

8個必須知道的Stream API使用方法

作者:酷學程式設計

作為一名java開發工程師,數組和集合在我的代碼中随處可見。我經常使用集合或數組來處理資料,如過濾和對象轉換。

我相信大家對數組的資料處理已經非常熟悉了。

On Java 中文版 進階卷 ¥66 購買

但是當資料處理比較複雜的時候,我們的代碼就會非常長,難以了解。

這個時候,我通常會把代碼拆成方法,并給出有意義的方法名稱,這樣可以解決一部分問題。然而,在java8之後,官方有了一個更有效、更友善的解決方案:Stream API。

Stream是Java8中處理集合的關鍵抽象。它可以指定你要對集合進行的操作,并且可以進行非常複雜的操作,如搜尋、過濾和映射資料。

使用Stream API對集合資料進行操作,類似于使用SQL進行資料庫查詢。

也可以使用Stream API來執行并行操作。簡而言之,Stream API提供了一種高效且易于使用的資料處理方式。

Stream具有以下特點:

  • 它不是一個資料結構,不儲存資料。
  • 懶惰評估,在流的中間處理過程中,隻記錄操作,不立即執行,直到執行終止操作才會進行實際計算。

今天我将分享一些工作中常用的、非常有用的API。

清單到地圖

在我們的工作中,經常會遇到清單或數組被轉換為地圖的場景。Collectors.toMap可以将List轉換成Map。

代碼如下:

public class ListToMap {

    public static void main(String[] args) {

        List<User> users = new ArrayList<>();
        users.add(new User(1, "Bob", 10));
        users.add(new User(2, "David", 22));
        users.add(new User(3, "Lance", 28));

        /**
         *  list to map
         *  (k1, k2) ->k1 indicates that if there is a duplicate key, the first key is retained and the second key is discarded
         */
        Map<String, User> userMap = users.stream().collect(Collectors.toMap(User::getUsername, user -> user, (k1, k2) -> k1));
        userMap.values().forEach(user->System.out.println(user.getUsername()));
    }
}           

同樣,還有Collectors.toList(),Collectors.toSet(),這意味着将相應的流轉換為一個List或Set。

使用groupingBy進行分組

分組在執行聚合資料操作時經常使用,比如按國籍對使用者進行分組。說到分組,相信大家都會想到SQL的group by。在Java8之前,我們可能需要這樣做:

List<User> users = Arrays.asList(new User(1, "Bob", 10,"America"),new User(2, "Daivd", 22,"America"),new User(3, "Lance", 28,"England"));

Map<String, List<User>> result = new HashMap<>();
for (User user : users) {
  String country = user.getCountry();
  List<User> userList = result.get(country);
  if (userList == null) {
      userList = new ArrayList<>();
      result.put(country, userList);
    }
  userList.add(user);
}           

如果你使用groupingBy,隻需要一行代碼就可以了:

Map<String, List<User>> result=users.stream.collect(Collectors.groupingBy(User::getCountry));           

使用限制和跳過的記憶體分頁

有時我們在記憶體中聚合資料後,資料量可能太大,無法一次性将資料傳回到前端。這個時候,就需要分頁。Stream api提供了limit和skip來完美支援它。

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
List<Integer> pageableList=list.stream.skip(3).limit(5).collect(Collectors.toList());           

使用filter()來過濾元素

從集合中過濾掉不符合标準的元素。

//Get all students older than 18
List<Student> studentNames = students.stream().filter(student->student.getAge()>18).collect(Collectors.toList());           

使用 sorted+Comparator 進行排序

在集合操作中,排序絕對是一個高頻的操作。雖然有現成的集合工具進行排序,但Stream api整合了這一功能,形成了自己的功能生态,進一步提高了api的便利性。

List<User> users = Arrays.asList(new User(1, "Bob", 10,"America"),
new User(2, "Daivd", 22,"America"),new User(3, "Lance", 28,"England"));
List<User> sortedUsers = users.stream().sorted(Comparator.comparing(User::getAge))
.collect(Collectors.toList());           

使用reduce進行聚合評估

Stream api也有一個非常有用的方法reduce()。使用reduce可以聚合集合中的所有元素,得到一個單一的值。最典型的情況是數組的總和。

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
Optional<Integer> sum=list.stream().reduce((a,b)->a+b);           

當然,你也可以使用reduce來執行其他的聚合操作,比如尋找一個數組的平均值。

使用map來轉換類型

map操作是對流中的元素進行重新處理,形成一個新的流。這在開發中很有用,例如,我有一個使用者的集合,但我隻需要使用使用者的名字和年齡,使用map方法就可以做到這點。

List<User> users = Arrays.asList(new User(1, "Bob", 10,"America"),new User(2, "Daivd", 22,"America"),new User(3, "Lance", 28,"England"));
List<UserVo> userVoList = users.stream().map(user->{
	UserVo userVo = new UserVo();
	userVo.setUsername(user.getUsername());
	userVo.setAge(user.getAge());
	return userVo;
}).collect(Collectors.toList());           

flatMap

flatMap操作可以将同一類型的多個流合并為一個流。

List<User> users = Arrays.asList(new User(1, "Bob", 10,"America"),new User(2, "Daivd", 22,"America"),new User(3, "Lance", 28,"England"));
List<User> userList = Arrays.asList(new User(4,"James",23,"America"));
List<List<User>> list = Arrays.asList(users,userList);

List<User> result = list.stream().flatMap(s->s.stream()).collect(Collectors.toList());           

最後

流API以聲明的方式處理集合資料,可以極大地提高Java程式員的工作效率,使我們能夠寫出高效、幹淨、簡潔的代碼。

我希望每個人都能掌握Stream Api,寫出優雅的代碼。謝謝你的閱讀!

On Java 中文版 進階卷 ¥66 購買

繼續閱讀