本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!html
首先分享以前的全部文章 , 歡迎點贊收藏轉發三連下次必定 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164…
Github : 👉 github.com/black-ant
CASE 國內備份 : 👉 gitee.com/antblack/ca…前端
Java 流這個特性已經出來好久了 , 能夠大大的減小咱們的代碼 , 並且並行處理能夠在某些場景下使用多個處理器核心能夠大大的提升性能.java
不過 Stream 語法新手使用起來仍是會有必定的難度 , 這一篇文檔由淺到深看一下這個特性.node
這是開篇 , 只記錄以前梳理的用法 , 下一篇來看源碼 , 記得收藏!!!!!git
Stream 的特色github
雙冒號運算就是將方法當成參數傳遞給須要的方法 ( Stream ) , 即爲方法引用算法
案例一 : 基礎用法json
x -> System.out.println(x)
// ------------
System.out::println
複製代碼
案例二 : 複雜用法後端
for (String item: list) {
AcceptMethod.printValur(item);
}
//------------------
list.faorEach(AcceptMethod::printValur);
複製代碼
基礎案例數組
// Collection 工具
Collection.stream () : list.stream();
Stream.<String>builder().add("a").add("b").add("c").build();
Stream.of("a", "b", "c")
Stream.generate(() -> "element").limit(10);
Stream.iterate(40, n -> n + 2).limit(20);
複製代碼
建立一個整數流
IntStream.rangeClosed(1, 100).reduce(0, Integer::sum);
IntStream.rangeClosed(1, 100).parallel().reduce(0, Integer::sum);
// 其餘的基本類型案例
LongStream.rangeClosed(1, 3);
複製代碼
建立一個並行流
// API :
Stream<E> parallelStream() // 案例 : Collection.parallelStream () listOfNumbers.parallelStream().reduce(5, Integer::sum);
listOfNumbers.parallelStream().forEach(number ->
System.out.println(number + " " + Thread.currentThread().getName())
);
複製代碼
數組建立流
Arrays.stream(intArray).reduce(0, Integer::sum);
Arrays.stream(intArray).parallel().reduce(0, Integer::sum);
Arrays.stream(integerArray).reduce(0, Integer::sum);
Arrays.stream(integerArray).parallel().reduce(0, Integer::sum);
複製代碼
合併流
// API : 組合2個 Streams
<T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) // 案例 Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> resultingStream = Stream.concat(stream1, stream2);
// 案例 : 合併三個
Stream.concat(Stream.concat(stream1, stream2), stream3);
// 案例 : stream of 合併流
Stream.of(stream1, stream2, stream3, stream4)
複製代碼
其餘的案例
// 靜態工廠
1. Java.util.stream.IntStream.range ( )
2. Java.nio.file.Files.walk ( )
// 手動建立
1. java.util.Spliterator
2. Random.ints()
3. BitSet.stream()
4. Pattern.splitAsStream(java.lang.CharSequence)
5. JarFile.stream()
// java.io.BufferedReader.lines()
Files.lines(path, Charset.forName("UTF-8"));
Files.lines(path);
複製代碼
補充
分割流案例
一個流能夠有多個 intermediate 操做 , 和一個 Terminal 操做 , 當 Terminal 執行完成後, 流就結束了
map : 元素映射
// API :
<R> Stream<R> map(Function<? super T, ? extends R> mapper) // Map 傳入方法函數 , Map 返回的是一個 object books.stream().filter(e -> "Effective Java".equals(e.getValue())).map(Map.Entry::getKey).findFirst();
wordList.stream().map(String::toUpperCase).collect(Collectors.toList());
Stream.of(1, 2, 3).map(n -> n + 1).collect(Collectors.toList());
nums.stream().map( n -> n * n ).collect (Collectors.toList());
複製代碼
flatMap
// flatMap 返回的是一個 Stream
Stream<List<String>> namesOriginalList = Stream.of(
Arrays.asList("Pankaj"),
Arrays.asList("David", "Lisa"),
Arrays.asList("Amit"));
//flat the stream from List<String> to String stream
Stream<String> flatStream = namesOriginalList
.flatMap(strList -> strList.stream());
flatStream.forEach(System.out::println);
複製代碼
mapToXXX
// API :
IntStream mapToInt(ToIntFunction<? super T> mapper) // 做用 : mapToXXX 主要用於轉換爲 doubleNumbers.stream().mapToDouble(Double::doubleValue).sum();
customers.stream().mapToInt(Customer::getAge).filter(c -> c > 65).count();
intStream1.mapToObj(c -> (char) c);
複製代碼
filter : 過濾 ,經過過濾的元素被流下來生成新的 stream
// Predicate 是一個函數式接口
Stream<T> filter(Predicate<? super T> predicate) // filter 中使用箭頭表達式 - tream<Integer> oddIntegers = ints.stream().filter(i -> i.intValue() % 2 != 0);
- list.stream().filter(p -> p.startsWith("j")).count()
// Filter 中使用 :: 雙冒號
customers.stream().filter(Customer::hasOverHundredPoints).collect(Collectors.toList());
// Filter 中使用代碼塊
customers.stream().filter(c -> {
try {
return c.hasValidProfilePhoto();
} catch (IOException e) {
//handle exception
}
return false;
}).collect(Collectors.toList());
複製代碼
distinct : 去重
nums.stream().filter(num -> num % 2 == 0).distinct().collect(Collectors.toList());
list.stream().distinct().collect(Collectors.toList())
複製代碼
sorted : 排序
// 自定義排序方式
persons.stream().limit(2).sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).collect(Collectors.toList());
// 使用指定 Comparator 提供的排序器
List<String> reverseSorted = names2.sorted(Comparator.reverseOrder()).collect(Collectors.toList());
// 不傳入參數使用默認排序方式
List<String> naturalSorted = names3.sorted().collect(Collectors.toList());
複製代碼
peek
// API : 能夠用於調試 ,主要在流經過管道中的某個點時進行攔截
Stream<T> peek(Consumer<? super T> action) // 案例 : IntStream.range(1, 10).peek(System.out::println).sum();
// 在多個攔截點攔截
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
複製代碼
limit : 限制
// API : 截斷流的數量 , 能夠看到仍是返回一個流
Stream<T> limit(long maxSize);
// 案例 :
nums.stream().filter(n-> n>2).limit(2).collect(Collectors.toList ())
複製代碼
skip : 跳過
// API :
Stream<T> skip(long n);
// 案例 :
nums. stream() .filter(n-> n>2 ).skip (2) . collect( Collectors . toList () );
複製代碼
parallel 並行流
// API : 返回一個並行的等效流 , 若是已是並行 ,返回自身
S parallel() boolean isParallel() // 案例 : Object[] listOutput = list.stream().parallel().toArray();
複製代碼
sequential : 串行流
// API :
S sequential();
// 案例 :
Arrays.asList(1, 2, 3, 4).stream().sequential();
複製代碼
unordered : 無序化
// 消除相遇順序 , 能夠提交併行性能
IntStream.range(1, 1_000_000).unordered().parallel().distinct().toArray();
複製代碼
foreach : 循環遍歷
// API : 能夠看到 , 這裏接受到的是一個 Consumer 函數
void forEach(Consumer<? super T> action);
// foreach 中使用箭頭函數
roster.stream().forEach(p -> System.out.println(p.getName()));
複製代碼
forEachOrdered : 有序的循環流
list.stream().parallel().forEachOrdered(e -> logger.info(e));
複製代碼
Array
stream.toArray(String[]::new);
//reduce : 把 Stream 元素組合起來
Stream.of("A", "B", "C", "D").reduce("", String::concat);
// reduce 求和
Stream.of(5, 6, 7, 8).reduce(0, (accumulator, element) -> accumulator + element);
?--- reduce 後面的參數 : 第一個默認值 , 後面是傳入的方法
// min : 將字符串數組求最大值
Stream.of(testStrings).max((p1, p2) -> Integer.compare(p1.length(), p2.length()));
// max : 得到最大長度
br.lines().mapToInt(String::length).max().getAsInt();
複製代碼
collection
// API
<R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
Map<String, Integer> hashMap = list.stream().collect(Collectors
.toMap(Function.identity(), String::length));
Map<String, Integer> linkedHashMap = list.stream().collect(Collectors.toMap(
Function.identity(),
String::length,
(u, v) -> u,
LinkedHashMap::new
));
// 建立 Collection 對象
Stream<Integer> intStream = Stream.of(1,2,3,4);
List<Integer> intList = intStream.collect(Collectors.toList());
System.out.println(intList); //prints [1, 2, 3, 4]
intStream = Stream.of(1,2,3,4); //stream is closed, so we need to create it again
Map<Integer,Integer> intMap = intStream.collect(Collectors.toMap(i -> i, i -> i+10));
System.out.println(intMap); //prints {1=11, 2=12, 3=13, 4=14}
// 建立 Array 對象
Stream<Integer> intStream = Stream.of(1,2,3,4);
Integer[] intArray = intStream.toArray(Integer[]::new);
System.out.println(Arrays.toString(intArray)); //prints [1, 2, 3, 4]
// String 操做
stream.collect(Collectors.joining()).toString();
list.stream().collect(Collectors.joining(" | ")) : 鏈接符中間穿插
list.stream().collect(Collectors.joining(" || ", "Start--", "--End")) : 鏈接符中間及先後
// 建立爲 Map
books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName));
// ps : Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper)
複製代碼
min : 返回此流的最小元素
// API
Optional<T> min(Comparator<? super T> comparator) Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator) // 案例 : list.stream().min(Comparator.comparing(String::valueOf)).ifPresent(e -> System.out.println("Min: " + e));
複製代碼
max : 返回此流的最大元素
// API
Optional<T> max(Comparator<? super T> comparator);
Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator)
// 案例 :
list.stream().max(Comparator.comparing(String::valueOf)).ifPresent(e -> System.out.println("Max: " + e));
複製代碼
count : 計算流中的項目數
// API :
<T> Collector<T, ?, Long>javacounting()
// 案例 :
Stream.of(1,2,3,4,5).count();
複製代碼
reduce
// API : reduce 用於 Stream 中進行計算處理
Optional<T> reduce(BinaryOperator<T> accumulator);
Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op)
U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);
Collector<T, ?, U> reducing(U identity,Function<? super T, ? extends U> mapper,BinaryOperator<U> op)
// 參數含義 :
identity : 縮減的標識值(也是沒有輸入元素時返回的值)
accumulator : 執行的操做
// 使用案例
numbers.reduce((i,j) -> {return i*j;});
numbers.stream().reduce(0, (subtotal, element) -> subtotal + element);
numbers.stream().reduce(0, Integer::sum);
// 關聯字符串
letters.stream().reduce("", (partialString, element) -> partialString + element);
// 關聯大小寫
letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase());
ages.parallelStream().reduce(0, a, b -> a + b, Integer::sum);
// 並行操做要點 : 並行處理運算必需要符合以下操做
1. 結果不受操做數順序的影響
2. 互不干擾: 操做不影響數據源
3. 無狀態和肯定性: 操做沒有狀態,而且爲給定的輸入生成相同的輸出
userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
複製代碼
anyMatch:任一元素知足匹配條件
// API : Stream 中只要有一個元素符合傳入的 predicate,返回 true
boolean anyMatch(Predicate<? super T> predicate);
// 案例 :
persons.stream(). anyMatch(p -> p.getAge() < 12);
複製代碼
allMatch:全部元素都知足匹配條件
// API : Stream 中所有元素符合傳入的 predicate,返回 true
boolean allMatch(Predicate<? super T> predicate);
// 案例 :
persons.stream(). allMatch(p -> p.getAge() > 18);
複製代碼
findFirst:返回Stream中的第一個元素
// API : 返回一個 Optional 標識第一個元素
Optional<T> findFirst();
// 案例 :
students.stream().filter(student ->student .getage()>20 ).findFirst();
複製代碼
findAny:返回Stream中的任意個元素
// API : findAny不必定返回第一個,而是返回任意一個 , 若是流爲空則返回一個空的Optional
Optional<T> findAny();
複製代碼
noneMatch:全部元素都不知足匹配條件
// API : 當Stream 中沒有一個元素符合傳入的 predicate,返回 true
boolean noneMatch(Predicate<? super T> predicate);
// 案例 :
numbers5.noneMatch(i -> i==10)
複製代碼
// reduce : 對參數化操做後的集合進行進一步操做
students.stream().filter(student -> "計算機科學".equals(student.getMajor())).map(Student::getAge).reduce(0, (a, b) -> a + b);
students.stream().filter(student -> "計算機科學".equals(student.getMajor())).map(Student::getAge).reduce(0, Integer::sum);
students.stream().filter(student -> "計算機科學".equals(student.getMajor())).map(Student::getAge).reduce(Integer::sum);
複製代碼
單級分組
// API :
public static <T, K> Collector<T, ?, Map<K, List<T>>>groupingBy(Function<? super T, ? extends K> classifier)
students.stream().collect(Collectors.groupingBy(Student::getSchool))
複製代碼
多級分組
// 做用 :
// 案例 :
students.stream().collect(
Collectors.groupingBy(Student::getSchool,
Collectors.groupingBy(Student::getMajor)));
複製代碼
partitioningBy : 分區 ,區別於groupBy ,分區中只有true , false .
// API : 能夠看到 , 這裏主要是 Predicate 函數
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,Collector<? super T, A, D> downstream)
// 案例 :
students.stream().collect(Collectors.partitioningBy(student -> "武漢大學".equals(student.getSchool())));
複製代碼
// 全局設置線程池
-D java.util.concurrent.ForkJoinPool.common.parallelism=4
// 手動設置線程此
ForkJoinPool customThreadPool = new ForkJoinPool(4);
int sum = customThreadPool.submit(
() -> listOfNumbers.parallelStream().reduce(0, Integer::sum)).get();
customThreadPool.shutdown();
複製代碼
List<JSONObject> itemjson = new LinkedList<JSONObject>();
List<A> aList = ...
itemCW.stream().map(c -> {
JSONObject nodeitem = new JSONObject();
nodeitem.put("whtype", 0);
return nodeitem;
}).forEach(c -> itemjson.add(c));
複製代碼
realmTO.getTemplates().forEach((key, template) -> {
AnyType type = anyTypeDAO.find(key);
anyTemplate.set(template);
});
// for-each 的時候 , 能夠傳入 key 和 對象 ,後續可使用
複製代碼
// 獲取id的集合
List<Long> idList = stockList.stream().map(Stock::getId).collect(Collectors.toList());
// 獲取skuid集合並去重
List<Long> skuIdList = stockList.stream().map(Stock::getSkuId).distinct().collect(Collectors.toList());
// 獲取supplierId集合(supplierId的類型爲int,返回List<Integer>,使用boxed方法裝箱)
Set<Integer> supplierIdSet = stockList.stream().mapToInt(Stock::getSupplierId).boxed().collect(Collectors.toSet());
複製代碼
// 按skuid分組
Map<Long, List<Stock>> skuIdStockMap = stockList.stream().collect(Collectors.groupingBy(Stock::getSkuId));
// 過濾supplierId=1而後按skuId分組
Map<Long, List<Stock>> filterSkuIdStockMap = stockList.stream().filter(s -> s.getSupplierId() == 1).collect(Collectors.groupingBy(Stock::getSkuId));
// 按狀態分爲不可用和其餘兩個分片
Map<Boolean, List<Stock>> partitionStockMap = stockList.stream().collect(Collectors.partitioningBy(s -> s.getStatus() == 0));
複製代碼
// 統計skuId=1的記錄數
long skuIdRecordNum = stockList.stream().filter(s -> s.getSkuId() == 1).count();
// 統計skuId=1的總庫存量
BigDecimal skuIdAmountSum = stockList.stream().filter(s -> s.getSkuId() == 1).map(Stock::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
複製代碼
// 多重分組並排序,先按supplierId分組,再按skuId分組,排序規則,先supplierId後skuId
Map<Integer, Map<Long, List<Stock>>> supplierSkuStockMap = stockList.stream().collect(Collectors.groupingBy(Stock::getSupplierId, TreeMap::new,
Collectors.groupingBy(Stock::getSkuId, TreeMap::new, Collectors.toList())));
// 多條件排序,先按supplierId正序排,再按skuId倒序排
// (非stream方法,而是集合的sort方法,直接改變原集合元素,使用Function參數)
stockList.sort(Comparator.comparing(Stock::getSupplierId)
.thenComparing(Stock::getSkuId, Comparator.reverseOrder()));
複製代碼
Collections.sort(literals, (final String t, final String t1) -> {
if (t == null && t1 == null) {
return 0;
} else if (t != null && t1 == null) {
return -1;
}
});
// t1 t2 是其中進行比較的了 2個對象 ,在裏面定義相關的排序方法,經過返回 true / false 返回排序規則
複製代碼
correlationRules.stream().filter(rule -> anyType != null && anyType.equals(rule.getAnyType())).findFirst()
// 關鍵在於 filter 和 findFirst
複製代碼
List<String> strings = Lists.transform(list, new Function<Integer, String>() {
@Override
public String apply(@Nullable Integer integer) {
return integer.toString();
}
});
複製代碼
return Stream.of(resources).map(resource -> preserveSubpackageName(baseUrlString, resource, path)).collect(Collectors.toList());
private String preserveSubpackageName(final String baseUrlString, final Resource resource, final String rootPath) {
try {
return rootPath + (rootPath.endsWith("/") ? "" : "/")
+ resource.getURL().toString().substring(baseUrlString.length());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
// 注意 ,其中調用了下面的方法 ,直接的匿名方法暫時不會寫
複製代碼
// 拼接成 [x, y, z] 形式
String result1 = stream1.collect(Collectors.joining(", ", "[", "]"));
// 拼接成 x | y | z 形式
String result2 = stream2.collect(Collectors.joining(" | ", "", ""));
// 拼接成 x -> y -> z] 形式
String result3 = stream3.collect(Collectors.joining(" -> ", "", ""));
(String)value.stream().map((i) -> {
return this.formatSql("{0}", i);
}).collect(Collectors.joining(",", "(", ")"));
複製代碼
buzChanlList.stream()
.map(item -> {
return null;
})
.filter(item -> {
return isok;
})
.forEach(c -> contentsList.add(c));
複製代碼
List<List<Integer>> splitList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> list.stream().skip(a * MAX_NUMBER).limit(MAX_NUMBER).parallel().collect(Collectors.toList())).collect(Collectors.toList());
複製代碼
collection.stream().filter(person -> "1".equals(person.getGender())).collect(Collectors.toList())
複製代碼
流的並行特性在使用得當的狀況下能夠大大增長效率 , 下一篇咱們來看一下源碼.
@ www.baeldung.com/intellij-de…