目錄
Java8新增的Stream + Lambda = !!!起飛,誰用誰知道!
什么是Stream?
Stream
將要處理的元素集合看作一種流,在流的過程中,借助Stream API
對流中的元素進行操作,比如:篩選、排序、聚合等。
Stream
可以由數組或集合創建,對流的操作分為兩種:
- 中間操作,每次返回一個新的流,可以有多個。
- 終端操作,每個流只能進行一次終端操作,終端操作結束后流無法再次使用。終端操作會產生一個新的集合或值。
另外,Stream
有幾個特性:
- stream不存儲數據,而是按照特定的規則對數據進行計算,一般會輸出結果。
- stream不會改變數據源,通常情況下會產生一個新的集合或一個值。
Stream的創建
public class BuildStream {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
// 通過集合的stream()方法創建順序流
Stream<Integer> stream1 = list.stream();
// 通過集合的parallelStream()方法創建順序流
Stream<Integer> parallelStream1 = list.parallelStream();
// 通過parallel()將順序流轉化為並行流
Stream<Integer> parallelStream2 = list.stream().parallel();
int[] arr = {1, 2, 3};
// 通過數組創建流
IntStream stream2 = Arrays.stream(arr);
// 通過Stream的靜態方法創建流
Stream<Integer> stream3 = Stream.of(1, 2, 3);
Stream<Integer> stream4 = Stream.iterate(1, x -> x + 1).limit(3);
stream1.forEach(x -> System.out.print(x + " "));
System.out.println(); // 1 2 3
parallelStream1.forEach(x -> System.out.print(x + " "));
System.out.println(); // 隨機
}
}
- stream是順序流,由主線程按順序對流執行操作。
- parallelStream是並行流,內部以多線程並行執行的方式對流進行操作,但前提流中的數據處理沒有順序要求。並行流能充分利用cpu優勢,在數據量足夠大的時候,加快處理速度。
測試API
新建測試數據
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Book {
Long id;
String title;
String author;
Integer pageCount;
Double price;
}
public class TestStream {
List<Book> bookList = new ArrayList<>();
@Before
public void init() {
bookList.add(Book.builder().author("天喬巴夏").id(1L).title("Java-Spring").pageCount(100).price(50d).build());
bookList.add(Book.builder().author("summerday").id(2L).title("Java-SpringBoot").pageCount(200).price(100d).build());
bookList.add(Book.builder().author("hyh").id(3L).title("mysql").pageCount(500).price(150d).build());
bookList.add(Book.builder().author("tqbx").id(4L).title("Linux").pageCount(30).price(10d).build());
}
}
findFirst、findAny
// 匹配第一個
Optional<Book> first = bookList.stream().filter(book -> book.getPageCount() > 100).findFirst();
first.ifPresent(book -> System.out.println("匹配第一個值 : " + book));
// 匹配任意
Optional<Book> any = bookList.parallelStream().filter(book -> book.getPageCount() > 100).findAny();
any.ifPresent(book -> System.out.println("匹配任意的值 : " + book));
anyMatch、noneMatch
// 是否包含符合條件的書
boolean anyMatch = bookList.stream().anyMatch(book -> book.getPageCount() > 100);
System.out.println("是否存在頁數大於100的書 : " + anyMatch);
// 檢查是否有名字長度大於5 的
boolean noneMatch = bookList.stream().noneMatch(book -> (book.getTitle().length() > 5));
System.out.println("不存在title長度大於5的書 : " + noneMatch);
filter
// 找到所有id為奇數的書,列出他們的書名到list中
List<String> titleList = bookList.stream()
.filter(book -> book.getId() % 2 == 1)
.map(Book::getTitle)
.collect(Collectors.toList());
System.out.println(titleList);
max、count
// 獲取頁數最多的書
Optional<Book> max = bookList.stream().max(Comparator.comparingInt(Book::getPageCount));
max.ifPresent(book -> System.out.println("頁數最多的書 : " + book));
// 計算mysql書籍有幾本
long count = bookList.stream().filter(book -> book.getTitle().contains("mysql")).count();
System.out.println("mysql書籍的本數 : " + count);
peek、map
// 將所有的書的價格調高100並輸出調高以后的書單
List<Book> result = bookList.stream().peek(book -> book.setPrice(book.getPrice() + 100))
.collect(Collectors.toList());
result.forEach(System.out::println);
// 獲取所有書的id列表
List<Long> ids = bookList.stream().map(Book::getId).collect(Collectors.toList());
System.out.println(ids);
reduce
// 求所有書籍的頁數之和
Integer totalPageCount = bookList.stream().reduce(0, (s, book) -> s += book.getPageCount(), Integer::sum);
System.out.println("所有書籍的頁數之和 : " + totalPageCount);
collect
// 將所有書籍存入 author -> title 的map中
Map<String, String> map = bookList.stream().collect(Collectors.toMap(Book::getAuthor, Book::getTitle));
// 取出所有id為偶數的書,存入list
List<Book> list = bookList.stream().filter(book -> book.getId() % 2 == 0).collect(Collectors.toList());
// 取出所有標題長度大於5的書,存入list
Set<Book> set = bookList.stream().filter(book -> book.getTitle().length() > 5).collect(Collectors.toSet());
count、averaging、summarizing、max、sum
// 統計書籍總數
Long bookCount = bookList.stream().filter(book -> "天喬巴夏".equals(book.getAuthor())).count();
// 求平均價格
Double average = bookList.stream().collect(Collectors.averagingDouble(Book::getPrice));
// 求最貴價格
Optional<Integer> max = bookList.stream().map(Book::getPageCount).max(Double::compare);
// 求價格之和
Integer priceCount = bookList.stream().mapToInt(Book::getPageCount).sum();
// 一次性統計所有信息
DoubleSummaryStatistics c = bookList.stream().collect(Collectors.summarizingDouble(Book::getPrice));
group
// 按書的價格是否高於100分組
Map<Boolean, List<Book>> part = bookList.stream().collect(Collectors.partitioningBy(book -> book.getPrice() > 100));
for (Map.Entry<Boolean, List<Book>> entry : part.entrySet()) {
if (entry.getKey().equals(Boolean.TRUE)) {
System.out.println("price > 100 ==> " + entry.getValue());
} else {
System.out.println("price <= 100 <== " + entry.getValue());
}
}
// 按頁數分組
Map<Integer, List<Book>> group = bookList.stream().collect(Collectors.groupingBy(Book::getPageCount));
System.out.println(group);
join
// 獲取所有書名
String titles = bookList.stream().map(Book::getTitle).collect(Collectors.joining(","));
System.out.println("所有書名 : " + titles);
sort
// 按價格升序
List<Book> sortListByPrice = bookList.stream().sorted(Comparator.comparing(Book::getPrice)).collect(Collectors.toList());
System.out.println(sortListByPrice);
// 按價格降序
List<Book> sortListByPriceReversed = bookList.stream().sorted(Comparator.comparing(Book::getPrice).reversed()).collect(Collectors.toList());
System.out.println(sortListByPriceReversed);
// 先價格再頁數
List<Book> sortListByPriceAndPageCount = bookList.stream().sorted(Comparator.comparing(Book::getPrice)
.thenComparing(Book::getPageCount)).collect(Collectors.toList());
System.out.println(sortListByPriceAndPageCount);
distinct、concat、limit、skip
Stream<Integer> stream1 = Stream.of(1, 2, 2, 3, 4);
Stream<Integer> stream2 = Stream.of(2, 3, 4, 5, 5);
// 合並
List<Integer> concatList = Stream.concat(stream1, stream2).collect(Collectors.toList());
System.out.println(concatList);
// 去重
List<Integer> distinctList = concatList.stream().distinct().collect(Collectors.toList());
System.out.println(distinctList);
// 限制
List<Integer> limitList = distinctList.stream().limit(3).collect(Collectors.toList());
System.out.println(limitList);
// 跳過
List<Integer> skipList = limitList.stream().skip(1).collect(Collectors.toList());
System.out.println(skipList);
// 迭代
List<Integer> iterateList = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
System.out.println(iterateList);
// 生成
List<Integer> generateList = Stream.generate(() -> new Random().nextInt()).limit(5).collect(Collectors.toList());
System.out.println(generateList);
boxed
int[]數組快速轉化為List
int[] arr = {1, 2, 3, 4, 5};
List<Integer> res = Arrays.stream(arr).boxed().collect(Collectors.toList());
System.out.println(res);
int[]數組逆序轉化為List或Array。
int[] arr = {1, 2, 3, 4, 5};
int[] res = Arrays.stream(arr)
.boxed() // 裝箱
.sorted(Comparator.reverseOrder())
.mapToInt(i -> i) // 轉為IntStream
.toArray();
List<Integer> collect = Arrays.stream(arr)
.boxed()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
Integer[] r = Arrays.stream(arr)
.boxed()
.sorted(Comparator.reverseOrder())
.toArray(Integer[]::new);