流是Java8引入的一個新特性,提供了對集合元素一系列便捷的操做,能夠用不多的代碼實現複雜的功能。
流有兩大類,分別是對象流(Stream),基本數據流(IntStream、LongStream、DoubleStream)。java
流的使用一般爲三個步驟:①建立流 ②描述流 ③求值數組
經過Stream靜態工廠方法來建立,Stream類提供瞭如下方法建立流。數據結構
建立好流以後,就能夠描述流了。更準確的說法是,聲明流的中間操做。
中間操做比較經常使用的有如下幾種(返回值爲Stream的均爲中間操做)框架
與中間操做相對應的是終端操做,也就是咱們的第三步,求值。
經常使用的終端操做有如下幾種(返回值不爲Stream的爲終端操做)dom
流是使用了內部迭代而不是外部迭代
內部迭代使用了惰性求值,只有在須要結果的那一刻才進行求值。
全部的中間操做(只描述流)都是惰性求值,由於只返回了Stream。
// 用戶類函數
public class User { private Integer id; private String name; private Integer age; // GET SET Constructor .. }
// 初始化數據調試
List<User> userList = new ArrayList<User>() { /** */ private static final long serialVersionUID = 1L; { add(new User(1, "Luffy", 17)); add(new User(2, "Zoro", 19)); add(new User(3, "Nami", 18)); add(new User(4, "Usopp", 17)); add(new User(5, "Sanji", 19)); add(new User(6, "Chopper", 15)); add(new User(7, "Robin", 28)); add(new User(8, "FRANKY", 34)); add(new User(9, "BROOK", 88)); } };
// 例子code
@Test public void test1() { // 獲取全部年齡大於17的用戶 List<User> users = userList.stream() .filter(user -> user.getAge() > 17) .collect(Collectors.toList()); System.out.println(users); } // 靜態導入Collectors後會更簡潔。 // import static java.util.stream.Collectors.*; @Test public void test2() { // 根據年齡是否大於17歲對集合進行分塊 Map<Boolean, List<User>> users = userList.stream() .collect(partitioningBy(u -> u.getAge() > 17)); System.out.println(users); } @Test public void test3() { // 按照年齡,將用戶分組 Map<Integer, List<User>> users = userList.stream() .collect(groupingBy(User::getAge)); System.out.println(users); } @Test public void test4() { // 獲取全部用戶的名稱 List<String> names = userList.stream() .map(User::getName) .collect(toList()); System.out.println(names); } @Test public void test5() { // 獲取年齡最大的用戶(只返回一個) User user = userList.stream() .max((u1, u2) -> { return u1.getAge() > u2.getAge() ? 1 : -1; }) .get(); System.out.println(user); } @Test public void test6() { // 獲取用戶年齡總和 int ageSum = userList.stream() .map(User::getAge) .reduce(0, (acc, element) -> { acc += element; return acc; }); System.out.println(ageSum); ageSum = userList.stream() .map(User::getAge) .reduce(0, Integer::sum); System.out.println(ageSum); ageSum = userList.stream() .collect(summingInt(User::getAge)); System.out.println(ageSum); } @Test public void test7() { // 獲取組成用戶姓名的字母 Set<String> set = userList.stream() .map(User::getName) .map(name -> name.split("")) .flatMap(Arrays::stream) .collect(toSet()); System.out.println(set); }
如何進行調試對象
// 能夠利用peek查看流中的數據狀態 userList.stream() .peek(System.out::println) .map(u -> u.getName()) .peek(System.out::println) .collect(toList());
使用並行仍是串行排序
// 將流改成並行流十分簡單,只須要將stream方法改成parallelStream Map<Integer, List<User>> users = userList.parallelStream() .collect(groupingBy(User::getAge)); // 或是使用 parallel() 聲明爲並行 Stream.iterate(0L, i -> i + 1) .parallel() .limit(10) .reduce(0L, Long::sum);
Java8流的並行屬於數據並行,即將數據分爲幾部分,利用多核CPU對每塊數據執行運算,最終彙總數據,獲得答案。底層是使用了fork/join框架,fork遞歸分解問題,而後每段並行執行,最終join合併結果。 所以,使用並行流須要考慮如下幾點: