1. 程式人生 > 其它 >JDK1.8之Stream API

JDK1.8之Stream API

技術標籤:javastreamlambda

jdk1.8的兩個重大改變,一個是Lambda表示式,另一個就是Stream API。Stream是jdk8中處理集合的關鍵抽象概念,可對集合進行復雜的查詢、過濾、篩選等操作。

流(Stream)的概念

流是資料渠道,用於操作資料來源,所生成一種新的元素序列。集合講的是資料,流講的是計算是操作。

需要注意的是:

  • Stream自身不會儲存元素
  • Stream不會改變資料來源物件,相反會返回產生一個持有結果的新Stream
  • Steam操作是延遲執行的,這意味著他們會等到需要結果的時候才執行。

流的操作步驟

  1. 建立Stream(獲取一個數據源(集合,陣列),從而獲取一個流)
  2. 用Stream中間操作(一箇中間操作鏈,用Stream API 對資料來源資料進行操作處理)
  3. 終止Stream操作(終止操作,執行中間鏈操作,併產生結果)

常見操作程式碼示例

  1. 示例資料準備
@Data
class Student{

    private String name;
    private Integer age;
    private String gender;

    public Student() {
    }

    public Student(String name, Integer age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

List<Student> stuList = new ArrayList<>();
stuList.add(new Student("張三", 18, "男"));
stuList.add(new Student("李四", 28, "女"));
stuList.add(new Student("王五", 16, "男"));
stuList.add(new Student("趙六", 30, "女"));
stuList.add(new Student("孫七", 35, "女"));
stuList.add(new Student("周八", 55, "男"));
  1. 過濾 filter
Stream<Student> stuStream = stuList.stream().filter(i -> i.getAge() > 18);
stuStream.forEach(System.out::println);
// 也可簡寫成
stuList.stream().filter(i -> i.getAge() > 18).forEach(a->{
    System.out.println(a.getName());
});

運算結果:

Student{name='李四', age=28, gender='女'}
Student{name='趙六', age=30, gender='女'}
Student{name='孫七', age=35, gender='女'}
Student{name='周八', age=55, gender='男'}
李四
趙六
孫七
周八
  1. limit 限定集合數量
stuList.stream().filter(i -> i.getAge() > 18).limit(2).forEach(a->{
    System.out.println(a.getName());
});

運算結果:

李四
趙六
  1. skip 跳過元素

skip和limit可一起使用可做分頁效果

stuList.stream().filter(i -> i.getAge() > 18).skip(2).limit(2).forEach(a->{
    System.out.println(a.getName());
});

運算結果:

孫七
周八
  1. distinct 去重

distinct()去重需要重寫實體類的hashCode()和equals()方法這裡僅示例String集合去重

List<String> list2 = new ArrayList<>();
list2.add("中");
list2.add("人");
list2.add("中");
list2.add("去");
list2.stream().distinct().forEach(a->{
    System.out.println(a);
});

運算結果:

中
人
去
  1. 排序 sorted
// 無引數排序
List<String> list2 = new ArrayList<>();
list2.add("e");
list2.add("c");
list2.add("b");
list2.add("z");
list2.stream().sorted().forEach(a->{
    System.out.println(a);
});
// 有引數排序
stuList.stream().sorted((o1, o2) ->  o2.getAge() - o1.getAge()).forEach(a->{
    System.out.println(a.getName());
});

運算結果:

b
c
e
z
周八
孫七
趙六
李四
張三
王五
  1. count 返回流中個數
long count = stuList.stream().count();

8.max 返回最大值 min 返回最小值

// 按年齡大小正序找最大值
Optional<Student> max = stuList.parallelStream().max((o1, o2) ->  o1.getAge() - o2.getAge());
System.out.println(max.get());
// 按年齡大小倒序找最大值
Optional<Student> max1 = stuList.parallelStream().max((o1, o2) ->  o2.getAge() - o1.getAge());
System.out.println(max1.get());

// 按年齡大小正序找最小值
Optional<Student> max2 = stuList.parallelStream().min((o1, o2) ->  o1.getAge() - o2.getAge());
System.out.println(max2.get());
// 按年齡大小倒序找最小值
Optional<Student> max3 = stuList.parallelStream().min((o1, o2) ->  o2.getAge() - o1.getAge());
System.out.println(max3.get());

運算結果:

Student{name='周八', age=55, gender='男'}
Student{name='王五', age=16, gender='男'}
Student{name='王五', age=16, gender='男'}
Student{name='周八', age=55, gender='男'}
  1. collect 將流轉換為其他形式
List<String> nameList = stuList.stream().map(Student::getName)
        .collect(Collectors.toList());
nameList.forEach(System.out::println);

運算結果:

張三
李四
王五
趙六
孫七
周八

Stream API還有其他操作,這裡僅記錄工作中常用API操作。其他操作用到時再做新增。