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更加友善。
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