java8中,除了Lambda表達式之外,還提供了強大的Stream API(java.util.stream.*),即流式編程。那什麼是流式編程?
什麼是流式編程 |
Stream是Java8中處理集合的關鍵抽象概念,它可以指定你想對集合進行的操作,比如:進行非複雜的查詢、過濾、或者映射數據等一系列的操作。Stream不是集合元素,也不是數據結構,它相當於一個高級版本的遍歷器(Iterator),不能夠重複遍歷裏面的數據,就像是流水一樣,流過就不再復返了。與普通的Iterator不同的是,普通的Iterator只能是串行,而Stream可以並行操作,這樣就大大提高了我們的操作速度。
注意:
1)Stream自己不會存儲元素
2)Stream的相關操作不會改變數據源。相反地他們會返回一個含有操作結果的新的Stream
Stream操作三步曲 |
1)創建 Stream
一個數據源(如:集合、數組),獲取一個Stream流
方法 | 描述 |
---|---|
stream() | 獲取串行流 |
parallelStream() | 獲取並行流 |
2)中間操作
在流的傳輸過程中,對Stream流進行處理
查詢
方法 | 描述 |
---|---|
allMatch(Predicate p) | 檢查是否匹配所有元素 |
anyMatch(Predicate p) | 檢查是否至少匹配一個元素 |
noneMatch(Predicate p) | 檢查是否沒有匹配所有元素 |
findFirst() | 返回第一個元素 |
findAny() | 返回當前流中的任意元素 |
篩選與切片
方法 | 描述 |
---|---|
distinct() | 篩選,通過流所生成的元素的hashCode()和equals()去除重複的元素(要去重的實體類需要重寫hashCode和equals方法) |
limit(long maxSize) | 截斷流,使其元素不超過給定數量 |
filter(Predicate p) | 接收Lambda,從流中排除掉某些元素 |
skip(long n) | 跳過元素,返回一個扔掉了前n個元素的流。若流中元素不足n個,則返回一個空流。與limit(n)互補 |
映射
方法 | 描述 |
---|---|
map(Function f) | 接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素 |
mapToInt(ToIntFunction f) | 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的IntStream |
mapToLong(ToLongFunction f) | 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的LongStream |
mapToDouble(ToDoubleFunction f) | 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的DoubleStream |
flatMap(Function f) | 接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連成一個流 |
排序
方法 | 描述 |
---|---|
sorted() | 產生一個新流,其中按自然順序排序 |
sorted(Comparator comp) | 產生一個新流,其中按比較器順序排序 |
comparable:自然排序
3)終止操作(終端操作)
終止操作返回的是一個結果,就是所有中間操作做完之後進行的操作,比如彙總、遍歷輸出、求和等等
Stream操作案例 |
這裏只是有選擇性的做了幾個案例,其實只要知道上面的“三步曲”,然後再知道點Lambda表達式,就能夠進行Stream流式編程了。
1)篩選與切片
List<Book> books = Arrays.asList(
new Book("三國演義", 20, "羅貫中"),
new Book("西遊記", 25, "吳承恩"),
new Book("水滸傳", 30, "施耐庵"),
new Book("紅樓夢", 35, "曹雪芹")
);
/**
* 篩選出price大於等於30的書籍
*/
@Test
void test1() {
//獲取流
Stream<Book> bookStream = books.stream()
//中間操作
.filter((book -> book.getPrice() >= 30));
//終止操作,遍歷輸出
bookStream.forEach(System.out::println);
}
/** 結果:
* Book{name='水滸傳', price=30, author='施耐庵'}
* Book{name='紅樓夢', price=35, author='曹雪芹'}
*/
2)排序
/**
* 排序
* List<Book> books = Arrays.asList(
* new Book("水滸傳", 30, "施耐庵"),
* new Book("西遊記", 25, "吳承恩"),
* new Book("三國演義", 20, "羅貫中"),
* new Book("紅樓夢", 35, "曹雪芹")
* );
*/
@Test
void test7() {
books.stream().sorted((b1, b2) -> {
if (b1.getPrice().equals(b2.getPrice())) {
return b1.getName().compareTo(b2.getName());
} else {
return b1.getPrice().compareTo(b2.getPrice());
}
}).forEach(System.out::println);
}
/**
* Book{name='三國演義', price=20, author='羅貫中'}
* Book{name='西遊記', price=25, author='吳承恩'}
* Book{name='水滸傳', price=30, author='施耐庵'}
* Book{name='紅樓夢', price=35, author='曹雪芹'}
*/
3)匹配
/**
* 匹配
* allMatch() :是否全部匹配,返回boolean
* anyMatch() :任意一個是否匹配,返回boolean
*/
@Test
void test8() {
System.out.println(books.stream().allMatch(book -> {
if (book.getPrice().equals(25)) {
return true;
}
return false;
}));
}
4)map映射
/**
* map 映射 獲取 所有book對象中最高的price
*/
@Test
void test9() {
Optional<Integer> max = books.stream()
.map(Book::getPrice)
.max(Integer::compareTo);
System.out.println("books中price最高爲:" + max.get());
}
/**
*books中price最高爲:30
*/