天天看點

Java 8 新特性 Stream

Java 8 新特性 Stream

Java 8 API添加了一個新的抽象稱為流Stream,可以讓你以一種聲明的方式處理資料。

Stream 使用一種類似用 SQL 語句從資料庫查詢資料的直覺方式來提供一種對 Java 集合運算和表達的高階抽象。

Stream API可以極大提高Java程式員的生産力,讓程式員寫出高效率、幹淨、簡潔的代碼。

這種風格将要處理的元素集合看作一種流, 流在管道中傳輸, 并且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。

元素流在管道中經過中間操作(intermediate operation)的處理,

最後由最終操作(terminal operation)得到前面處理的結果。

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+
           

以上的流程轉換為 Java 代碼為:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();
           

應用場景

mans 類有很多卡類,先初始化一些資料。

List<Man> mans = new ArrayList<>();
        mans.add(new Man("001","張三",Arrays.asList(new Card("工商銀行","9558800001"),new Card("工商銀行","9558800002"),new Card("建設銀行","6227001234"))));
        mans.add(new Man("002","李四",Arrays.asList(new Card("招商銀行","6225800002"),new Card("建設銀行","6227035248"))));
        mans.add(new Man("003","王五",Arrays.asList(new Card("建設銀行","6227056547"),new Card("中國銀行","6013832547"),new Card("民生銀行","4074058542"))));
        mans.add(new Man("004","趙六",Arrays.asList(new Card("工商銀行","9558832458"),new Card("工商銀行","9558832547"),new Card("建設銀行","6227032578"))));
        mans.add(new Man("005","孫七",Arrays.asList(new Card("中國銀行","6013825847"),new Card("農業銀行","6228836547"),new Card("招商銀行","6225014582"))));
        mans.add(new Man("006","張三",Arrays.asList(new Card("工商銀行","9558832587"),new Card("交通銀行","6222814578"),new Card("工商銀行","9558865427"))));
           

1,查找張三的男人,for是這樣的,

public List<Man> getByName(List<Man> mans){
        List<Man> temp = new ArrayList<>();
        for(Man man : mans){
            if("張三".equals(man.getName())){
                temp.add(man);
            }
        }
        return temp;
    }
           

改進後:

public List<Man> getByName8(List<Man> mans) {
        return mans.stream().filter(m -> "張三".equals(m.getName())).collect(Collectors.toList());
    }
           

這裡的集合相當與資料庫的表,而filter相當于資料庫的where。 

filter 方法 : 用于通過設定的條件過濾出元素。

2,繼續,查找id為007的男人,id唯一,for是這樣的

public Man getById(List<Man> mans) {
        for (Man man : mans) {
            if ("007".equals(man.getId())) {
                return man;
            }
        }
        return null;
    }
           

改進後:

public Man getById8(List<Man> mans) {
        return mans.stream().filter(m -> "oo7".equals(m.getId())).findFirst().orElse(null);
    }
           

3,繼續,擷取名字叫張三(因有同名)的所有銀行卡,這裡不讨論實際業務意義,隻講技術,哈哈,用for是這樣的。

public List<Card> getAllCardByName(List<Man> mans) {
        List<Card> cards = new ArrayList<>();
        for (Man man : mans) {
            if ("張三".equals(man.getName())) {
                cards.addAll(man.getCards());
            }
        }
        return cards;
    }
           

改進後:

public List<Card> getAllCardByName8(List<Man> mans) {
        return mans.stream().filter(m -> "張三".equals(m.getName())).flatMap(m -> m.getCards().stream())
                .collect(Collectors.toList());
    }
           

https://blog.csdn.net/weixin_41888813/article/details/82908534           Java8Stream map和flatmap的差別

Collectors 類實作了很多歸約操作,例如将流轉換成集合和聚合元素。Collectors 可用于傳回清單或字元串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("篩選清單: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字元串: " + mergedString);
           

4,繼續,在3的條件上加個工商銀行條件,for

public List<Card> getSomeCardByName(List<Man> mans) {
        List<Card> cards = new ArrayList<>();
        for (Man man : mans) {
            if ("張三".equals(man.getName())) {
                for (Card card : man.getCards()) {
                    if ("工商銀行".equals(card.getName())) {
                        cards.add(card);
                    }
                }
            }
        }
        return cards;
    }
           

改進後:

public List<Card> getSomeCardByName8(List<Man> mans) {
        return mans.stream().filter(m -> "張三".equals(m.getName())).flatMap(m -> m.getCards().stream())
                .filter(c -> "工商銀行".equals(c.getName())).collect(Collectors.toList());
    }
           

5,把張三的名字修改為新張三,for,注意會改變源資料

public List<Man> changeName(List<Man> mans) {
        for (Man man : mans) {
            if ("張三".equals(man.getName())) {
                man.setName("新張三");
            }
        }
        return mans;
    }
           

改進:

public List<Man> changeName8(List<Man> mans) {
        return mans.stream().peek(m -> {
            if ("張三".equals(m.getName()))
                m.setName("新張三");
        }).collect(Collectors.toList());
    }
           

實測使用peek好像會有些問題,還是直接使用forEach更加友善。 

Java 8 新特性 Stream
orElseThrow()

如果有值則将其傳回,否則抛出supplier接口建立的異常。

try {
  empty.orElseThrow(()->new RuntimeException());
} catch (Throwable ex) {
  //輸出: No value present in the Optional instance
  System.out.println(ex.getMessage());
}
           
案例1 :根據Age 分組,并且拆分成兩個group
           
12 public class GroupByDemo {
13     public static void main(String[] args) {
14         Student student1 = new Student(200, "yangtao", "1");
15         Student student2 = new Student(220, "yangtao", "1");
16         Student student3 = new Student(500, "yangtao", "2");
17         Student student4 = new Student(504, "yangtao", "2");
18         List<Student> studentList =new ArrayList<>();
19         studentList.add(student1);
20         studentList.add(student2);
21         studentList.add(student3);
22         studentList.add(student4);
23 
24         //單一分組條件,根據code
25         Map<String, List<Student>> singleMap = studentList.stream().collect(Collectors.groupingBy(Student::getCode));
26         //{1=[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}],
27         // 2=[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}]}
28 
29         //組合分組條件
30 
31         Map<String, List<Student>> complexMap = studentList.stream().collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
32         List<Student> studentList1 = complexMap.get("yangtao+1");
33         List<Student> studentList2 = complexMap.get("yangtao+2");
34         System.out.println(complexMap);
35 //       {yangtao+2=[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}], yangtao+1=[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}]}
36 
37         System.out.println(studentList1);
38         System.out.println(studentList2);
39         //[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}]
40         //[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}]
41 
42     }
43     private static String fetchGroupKey(Student student){
44         return student.getUsername() +"+"+ student.getCode();
45     }
46 
47 }
           

參考來源于:

https://blog.csdn.net/williamtsang/article/details/52634970

繼續閱讀