This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!
>>>> 😜😜😜 Github: 👉 github.com/black-ant CASE Domestic backup: 👉 gitee.com/antblack/ca…
A. The preface
Java streams are a feature that has been around for a long time and can greatly reduce our code, and parallel processing can greatly improve performance by using multiple processor cores in some scenarios.
While Stream syntax can be tricky for beginners to use, this article takes a look at this feature from the shallow to the deep.
This is the beginning, only record the previous combing usage, the next article to see the source code, remember to collect!!!!!
The characteristics of the Stream
- Stream is not a collection, nor is it a data structure, and cannot hold data
- A Stream is somewhat similar to a high-level Iterator and can be used for algorithms and calculations
- Unlike iterators, streams can be parallelized, and the data is divided into segments that are processed in different threads
- Data source, zero or more intermediate operations, and zero or one terminal operation
- All intermediate operations are inert and have no effect until the pipe starts working
- The terminal operation is a bit like a faucet. When the faucet is opened, the water flows and the intermediate operation is performed
Ii. Basic knowledge
2.1 Structure operation
2.1.1 Double colon operation
The double colon operation is to pass the method as an argument to the desired method (Stream), which is a method reference
Example 1: Basic usage
x -> System.out.println(x)
// ------------
System.out::println
Copy the code
Case 2: Complex usage
for (String item: list) {
AcceptMethod.printValur(item);
}
//------------------
list.faorEach(AcceptMethod::printValur);
Copy the code
2.2 Stream creation
2.2.1 Collection and array tools
Based on the case
/ / Collection tools
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);
Copy the code
Create an integer stream
IntStream.rangeClosed(1.100).reduce(0, Integer::sum);
IntStream.rangeClosed(1.100).parallel().reduce(0, Integer::sum);
// Other basic types of cases
LongStream.rangeClosed(1.3);
Copy the code
Create a parallel flow
// API :
Stream<E> parallelStream(a)
/ / case:
Collection.parallelStream (a)
listOfNumbers.parallelStream(a).reduce(5, Integer::sum);
listOfNumbers.parallelStream().forEach(number ->
System.out.println(number + "" + Thread.currentThread().getName())
);
Copy the code
Array creation stream
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);
Copy the code
Combined flow
// API: combine two Streams
<T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
/ / case
Stream<Integer> stream1 = Stream.of(1.3.5);
Stream<Integer> stream2 = Stream.of(2.4.6);
Stream<Integer> resultingStream = Stream.concat(stream1, stream2);
// Example: merge three
Stream.concat(Stream.concat(stream1, stream2), stream3);
// Example: stream of merge streamStream.of(stream1, stream2, stream3, stream4)Copy the code
Other cases
// Static factory
1. Java.util.stream.IntStream.range ( )
2. Java.nio.file.Files.walk ( )
// Create manually
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);
Copy the code
supplement
Split flow Case
2.3 Stream Operations
A flow can have multiple Intermediate operations and one Terminal operation, and when the Terminal completes, the flow ends
2.3.1 Intermediate Operation of a flow
Map: indicates the element mapping
// API :
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
// Map is passed in the method function, and the Map returns an object
books.stream(a).filter(e -> "Effective Java".equals(e.getValue())).map(Map.Entry::getKey).findFirst(a);
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());
Copy the code
flatMap
// flatMap returns a 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);
Copy the code
mapToXXX
// API :
IntStream mapToInt(ToIntFunction<? super T> mapper)
MapToXXX is mainly used to convert to
doubleNumbers.stream(a).mapToDouble(Double::doubleValue).sum(a);
customers.stream().mapToInt(Customer::getAge).filter(c -> c > 65).count();
intStream1.mapToObj(c -> (char) c);
Copy the code
A new stream is generated from the elements that are filtered
Predicate is a functional interface
Stream<T> filter(Predicate<? super T> predicate)
// Use the arrow expression in the filter
- tream<Integer> oddIntegers = ints.stream().filter(i -> i.intValue() % 2! =0);
- list.stream().filter(p -> p.startsWith("j")).count()
// Double colons are used in the Filter ::
customers.stream().filter(Customer::hasOverHundredPoints).collect(Collectors.toList());
// Use code blocks in Filter
customers.stream().filter(c -> {
try {
return c.hasValidProfilePhoto();
} catch (IOException e) {
//handle exception
}
return false;
}).collect(Collectors.toList());
Copy the code
Distinct: go to heavy
nums.stream().filter(num -> num % 2= =0).distinct().collect(Collectors.toList());
list.stream().distinct().collect(Collectors.toList())
Copy the code
Sorted: sorting
// Customize the sorting mode
persons.stream().limit(2).sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).collect(Collectors.toList());
// Use the collator provided by the specified Comparator
List<String> reverseSorted = names2.sorted(Comparator.reverseOrder()).collect(Collectors.toList());
// Use default sort with no parameters
List<String> naturalSorted = names3.sorted().collect(Collectors.toList());
Copy the code
peek
// API: can be used for debugging, mainly to intercept the flow as it passes through a certain point in the pipeline
Stream<T> peek(Consumer<? super T> action)
/ / case:
IntStream.range(1.10).peek(System.out::println).sum(a);
// Intercept at multiple intercept points
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());
Copy the code
Limit: limit
// API: the number of streams to truncate. You can see that a stream is still returned
Stream<T> limit(long maxSize);
/ / case:
nums.stream().filter(n-> n>2).limit(2).collect(Collectors.toList ())
Copy the code
Skip, skip
// API :
Stream<T> skip(long n);
/ / case:
nums. stream() .filter(n-> n>2 ).skip (2) . collect( Collectors . toList () );
Copy the code
The parallel parallel flows
// API: returns a parallel equivalent stream, or itself if already parallel
S parallel(a)
boolean isParallel(a)
/ / case:
Object[] listOutput = list.stream().parallel().toArray();
Copy the code
Sequential: a serial stream
// API :
S sequential(a);
/ / case:
Arrays.asList(1.2.3.4).stream().sequential();
Copy the code
Unordered: indicates the unordered state
// Eliminate the encounter order, so that parallel performance can be committed
IntStream.range(1.1 _000_000).unordered().parallel().distinct().toArray();
Copy the code
2.3.2 Aggregation of Terminal operations of streams
Foreach: loop traversal
// API: As you can see, a Consumer function is received
void forEach(Consumer<? super T> action);
// Use the arrow function in foreach
roster.stream().forEach(p -> System.out.println(p.getName()));
Copy the code
ForEachOrdered: A circular flow that is ordered
list.stream().parallel().forEachOrdered(e -> logger.info(e));
Copy the code
Array
stream.toArray(String[]::new);
//reduce: combine the Stream elements
Stream.of("A"."B"."C"."D").reduce("", String::concat);
/ / reduce sum
Stream.of(5.6.7.8).reduce(0, (accumulator, element) -> accumulator + element); ? - Parameters after reduce: the first default value followed by the passed method// min: maximizes the string array
Stream.of(testStrings).max((p1, p2) -> Integer.compare(p1.length(), p2.length()));
// Max: gets the maximum length
br.lines().mapToInt(String::length).max().getAsInt();
Copy the code
collection
- Stream.collect (aggregators.tolist ()) : toList collects all elements of the stream into the List
- Stream.collect (Collectors. ToCollection (ArrayList::new)): Collects the elements of a stream into a collection created by a given source
- Stream.collect (collects.toset ()) : Saves all elements in the stream to a Set, removing the duplicate lock
- stream.collect(Collectors.toCollection(Stack::new))
// 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
));
// Create a Collection object
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}
// Create an Array object
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 operations
stream.collect(Collectors.joining()).toString();
list.stream().collect(Collectors.joining("|")) : list.stream().collect(collection.joining ()"| |"."Start--"."--End")) : the middle and before and after the hyphen// Create a Map
books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName));
// ps : Collector
> toMap(Function
keyMapper,Function
valueMapper)
,>
Copy the code
2.3.3 Calculation of Terminal operation of streams
Min: Returns the smallest element of this stream
// API
Optional<T> min(Comparator<? super T> comparator)Collector<T, ? , Optional<T>>minBy(Comparator<? super T> comparator)
/ / case:
list.stream(a).min(Comparator.comparing(String::valueOf)).ifPresent(e -> System.out.println("Min: " + e));
Copy the code
Max: Returns the largest element of this stream
// API
Optional<T> max(Comparator<? super T> comparator); Collector<T, ? , Optional<T>> maxBy(Comparator<?super T> comparator)
/ / case:
list.stream().max(Comparator.comparing(String::valueOf)).ifPresent(e -> System.out.println("Max: " + e));
Copy the code
Count: Counts the number of items in the stream
// API : <T> Collector<T, ? , Long>javacounting()/ / case:
Stream.of(1.2.3.4.5).count();
Copy the code
reduce
// API: Reduce is used to perform computation in 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)
// The parameters are as follows:Identity: reduced identifier value (also returned with no input element) accumulator: Operation performed// Use case
numbers.reduce((i,j) -> {returni*j; }); numbers.stream().reduce(0, (subtotal, element) -> subtotal + element);
numbers.stream().reduce(0, Integer::sum);
// Association string
letters.stream().reduce("", (partialString, element) -> partialString + element);
// Case correlation
letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase());
ages.parallelStream().reduce(0, a, b -> a + b, Integer::sum);
// Parallel operation: parallel processing operations must comply with the following operations
1.The result is not affected by the order of operands2.Non-interference: Operations do not affect the data source3.Stateless and deterministic: Operations are stateless and generate the same output for a given input userList.parallelStream().reduce()0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
Copy the code
2.4 Search for Terminal operations of streams
AnyMatch: Any element meets the matching condition
// API: Return true as long as one of the elements in Stream matches the predicate passed in
boolean anyMatch(Predicate<? super T> predicate);
/ / case:
persons.stream(). anyMatch(p -> p.getAge() < 12);
Copy the code
AllMatch: All elements meet the matching condition
// API: Return true for all elements of Stream that match the predicate passed in
boolean allMatch(Predicate<? super T> predicate);
/ / case:
persons.stream(). allMatch(p -> p.getAge() > 18);
Copy the code
FindFirst: Returns the first element in Stream
// API: returns an Optional identifier for the first element
Optional<T> findFirst(a);
/ / case:
students.stream().filter(student ->student .getage()>20 ).findFirst();
Copy the code
FindAny: Returns any element in Stream
// API: findAny does not necessarily return the first, but either, or an empty Optional if the stream is empty
Optional<T> findAny(a);
Copy the code
NoneMatch: None of the elements meet the match condition
// API: Returns true if none of the elements in Stream match the predicate passed in
boolean noneMatch(Predicate<? super T> predicate);
/ / case:
numbers5.noneMatch(i -> i==10)
Copy the code
2.5 Stream specification
// Reduce: perform further operations on the parameterized collection
students.stream().filter(student -> "Computer Science".equals(student.getMajor())).map(Student::getAge).reduce(0, (a, b) -> a + b);
students.stream().filter(student -> "Computer Science".equals(student.getMajor())).map(Student::getAge).reduce(0, Integer::sum);
students.stream().filter(student -> "Computer Science".equals(student.getMajor())).map(Student::getAge).reduce(Integer::sum);
Copy the code
2.6 Grouping streams By
Single-stage grouping
// 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))
Copy the code
Multistage grouping
/ / function:
/ / case:
students.stream().collect(
Collectors.groupingBy(Student::getSchool,
Collectors.groupingBy(Student::getMajor)));
Copy the code
PartitioningBy: specifies a partition. Unlike groupBy, partitions can only be true and false.
// API: As you can see, this is mainly Predicate functionsCollector<T, ? , Map<Boolean, List<T>>> partitioningBy(Predicate<?superT> predicate) Collector<T, ? , Map<Boolean, D>> partitioningBy(Predicate<?super T> predicate,Collector<? super T, A, D> downstream)
/ / case:
students.stream().collect(Collectors.partitioningBy(student -> "Wuhan University".equals(student.getSchool())));
Copy the code
3. Use in-depth
3.1 Extending the thread pool
// Set thread pool globally
-D java.util.concurrent.ForkJoinPool.common.parallelism=4
// Manually set this thread
ForkJoinPool customThreadPool = new ForkJoinPool(4);
int sum = customThreadPool.submit(
() -> listOfNumbers.parallelStream().reduce(0, Integer::sum)).get();
customThreadPool.shutdown();
Copy the code
3.2 the Debug process
4. Common cases
Example 1: Each element in List AList is converted to generate another type C and put it into List BList
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));
Copy the code
Case 2: Loop through a Map
realmTO.getTemplates().forEach((key, template) -> {
AnyType type = anyTypeDAO.find(key);
anyTemplate.set(template);
});
// For each, you can pass in the key and object, which can be used later
Copy the code
Case 3: Getting a small collection from a large collection
// Get a collection of ids
List<Long> idList = stockList.stream().map(Stock::getId).collect(Collectors.toList());
// Get the skUID set and deduplicate it
List<Long> skuIdList = stockList.stream().map(Stock::getSkuId).distinct().collect(Collectors.toList());
// Get a set of supplierIds (supplierId = int, return List
, boxed)
Set<Integer> supplierIdSet = stockList.stream().mapToInt(Stock::getSupplierId).boxed().collect(Collectors.toSet());
Copy the code
Case 4: Grouping and sharding
// Group by skuid
Map<Long, List<Stock>> skuIdStockMap = stockList.stream().collect(Collectors.groupingBy(Stock::getSkuId));
// Filter supplierId=1 and group by skuId
Map<Long, List<Stock>> filterSkuIdStockMap = stockList.stream().filter(s -> s.getSupplierId() == 1).collect(Collectors.groupingBy(Stock::getSkuId));
// Partitions are divided into unavailable and other fragments by state
Map<Boolean, List<Stock>> partitionStockMap = stockList.stream().collect(Collectors.partitioningBy(s -> s.getStatus() == 0));
Copy the code
Case 5: Counting and Summing
Count the number of records whose skuId=1
long skuIdRecordNum = stockList.stream().filter(s -> s.getSkuId() == 1).count();
// Count the total inventory with skuId=1
BigDecimal skuIdAmountSum = stockList.stream().filter(s -> s.getSkuId() == 1).map(Stock::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
Copy the code
Case 6: Specific usage
// Group by supplierId and then by skuId. Sort by supplierId and then 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 (supplierId) and skuId (skuId)
// sort (); // sort (); // sort ();
stockList.sort(Comparator.comparing(Stock::getSupplierId)
.thenComparing(Stock::getSkuId, Comparator.reverseOrder()));
Copy the code
Case 7: Sorting by convection
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 and t2 are the objects to be compared, and the collation method is defined in them. Return true/false for collation
Copy the code
Case 8: Get the first one after filtering the flow
correlationRules.stream().filter(rule -> anyType ! =null && anyType.equals(rule.getAnyType())).findFirst()
// The key is filter and findFirst
Copy the code
Case 9: Conversion from one set of types to another
List<String> strings = Lists.transform(list, new Function<Integer, String>() {
@Override
public String apply(@Nullable Integer integer) {
returninteger.toString(); }});Copy the code
Case 10: Traversing a collection and returning a collection
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 newUncheckedIOException(e); }}// Note that the following method is called. The direct anonymous method is not written for the time being
Copy the code
Case 11: Simple splicing
// Splice [x, y, z]
String result1 = stream1.collect(Collectors.joining(","."["."]"));
/ / splicing into x | y | z forms
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(","."(".")"));
Copy the code
Case 12: Complex use
buzChanlList.stream()
.map(item -> {
return null;
})
.filter(item -> {
return isok;
})
.forEach(c -> contentsList.add(c));
Copy the code
Case 13: Syncopated sets
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());
Copy the code
Case 14: Filter operation
collection.stream().filter(person -> "1".equals(person.getGender())).collect(Collectors.toList())
Copy the code
conclusion
The parallelism of streams can greatly increase efficiency when used properly, and we’ll look at the source code in the next article.
reference
@ www.it610.com/article/129…
@ www.baeldung.com/intellij-de…
@ Java 8 Stream – Java Stream – JournalDev
@ www.baeldung.com/java-stream…