This is the 20th day of my participation in the August Text Challenge.More challenges in August
Lambda
A form of an anonymous function that has no name but a list of arguments, return types, and exceptions.
Custom functional interfaces
- There can only be one abstract method in an interface, but there can be more than one
default
Methods. - Comment on the interface
@FunctionalInterface
The annotations and@Override
Similarly, it is a specification and can be omitted, but an error will be reported at compile time if the interface definition does not conform to the specification.
Eg:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Copy the code
Common functional interfaces
-
Predicate
Accept generics and return Boolean
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Copy the code
-
Consumer
Accept the generic type and return void
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Copy the code
-
Function
Receiving generic T returns generic R
@FunctionalInterface
public interface Function<T.R> {
R apply(T t);
}
Copy the code
- Supplier
Returns the generic T with no input parameter
@FunctionalInterface
public interface Supplier<T>{
T get(a);
}
Copy the code
- Runnerable
@FunctionalInterface
public interface Runnable {
public abstract void run(a);
}
Copy the code
Method references
A shortcut for calling a lambda for a particular method; A grammatical sugar.
If a Lambda simply stands for “call a method directly,” the call can be made directly by the method name.
The target reference is preceded by the :: delimiter, followed by the method
eg:
System.out::println
Constructor reference
For an existing constructor, you can use the name and keyword new to create a reference to it. ClassName::new does the same thing as pointing to a static reference.
eg:
class Apple{
public Apple(a){}
public Apple(Integer integer) {}
}
Supplier<Apple> s = Apple::new;
Function<Integer,Apple> f = Apple::new;
Copy the code
Stream
Streams exist for computation, collections exist for storage.
Eg: The following scenario: There is a string of numbers, and it is required to print the even numbers in the string without repeating them.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 4, 34, 65, 45, 765, 67, 325, 23);
- If we write it ourselves, first of all, find the even number, store it in the Set, and then print it through the Set.
HashSet<Integer> integerHashSet = new HashSet<>();
for(Integer temp:numbers){
if(temp%2= =0){ integerHashSet.add(temp); }}for(Integer temp:integerHashSet){
System.out.println(temp);
}
Copy the code
- After using stream calculation
numbers.stream()
.filter(i->i%2= =0)
.distinct()
.forEach(System.out::println);
Copy the code
By contrast, the use of stream greatly simplifies development, and most importantly, we used the for loop twice before, but with the use of stream, instead of writing the loop statement, the developer handed the loop statement inside the stream. The advantage of this is that developers don’t have to worry about how the loop is iterated internally, which greatly simplifies development and readability.
Common flow operations
The method signature | instructions |
---|---|
Stream<T> limit(long n); |
Returns the stream of the first n elements |
Stream<T> skip(long n); |
Returns a stream that skips the first n elements |
<R> Stream<R> map(Function<? super T, ? extends R> mapper) |
Take a function as an argument and map it to a new element |
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); |
Flatten all streams into one stream |
boolean allMatch(Predicate<? super T> predicate); |
Check that the predicate matches all elements |
boolean anyMatch(Predicate<? super T> predicate); |
Check that the predicate matches at least one element |
boolean noneMatch(Predicate<? super T> predicate); |
Whether no element of the content in the stream matches the given |
Optional<T> findFirst(); |
Returns the first element in the stream |
Optional<T> findAny(); |
Returns any element in the stream |
FindFirst has more constraints than findAny and takes longer to execute.
Optional
Is a container class that represents the presence or absence of a value. His presence avoids null-pointer exceptions.
- IsPresent () Optional includes returns true if it is worth it, false otherwise
- IfPresent (Consumer Block) Optional executes the given code if it exists
- T get() Optional returns the value if it exists, otherwise raises NoSuchElement
- T orElse(T Other) Returns the value if the value exists, otherwise the default value is returned.
reduction
Reduce a function that provides iteration
Reduce accepts two parameters:
- An initial value
- a
BinaryOperator<T>
To combine elements to produce a new value
In addition, an overloaded method is provided
Initial values are not accepted. But it will return an Optional object. (Return Optional in case the computed value does not exist)
Eg:
Computes the sum of the given List.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
- Traditional for-each
int count = 0;
for(Integer t:numbers){
count+=t;
}
Copy the code
- Lambda
Integer count = numbers.stream()
.reduce(0, (a, b) -> a + b);
Copy the code
Numerical flow
In the example above, where the elements are “unboxed” and evaluated during each iteration, which is a waste of time, Java provides an elegant stream for manipulating primitive data types.
-
Common methods for mapping to numeric streams: mapToInt, mapToDouble, and mapToLong.
-
The response’s numeric stream is replaced with an object stream method: boxed.
Build flow
-
The flow is created from the value, just as it was created before.
Stream<String> stringStream = Stream.of("python"."groovy"."scala"); Copy the code
-
Create streams from arrays
int numbers[] = {3.2.5.8.4.7.6.9}; Arrays.stream(numbers); Copy the code
-
A stream is generated from a file
NIO, which handles file I/O operations in Java,
try(Stream<String> lines = Files.lines(Paths.get("filepath"),Charset.defaultCharset())) { ... } catch (IOException e) { e.printStackTrace(); } Copy the code
-
Generate streams from functions: Create infinite streams
Stream AP provides two static methods to generate streams from functions, stream.iterate&stream.generate
The generated stream will be endlessly evaluated by the function passed in, and should be limited with the use of limits.
-
iterate
Iterate takes an initial value, and a Lambda applied once for each new value produced
eg:
Stream.iterate(0,n->n+2) .limit(10) .forEach(System.out::println); Copy the code
-
generate
Generate accepts a Lambda that generates a new value
Eg:
Stream.generate(Math::random) .limit(5) .forEach(System.out::println); Copy the code
The collector
The collector provides three main functions
-
- Specify and summarize elements into a value
- Grouping elements
- Element partition
The wheel test
- Find the maximum value in the stream
public void test6(a) {
Optional<Dish> mostCalorieDish = menu.stream().max(comparingInt(Dish::getCalories));
System.out.println(mostCalorieDish.get().getName());
}
Copy the code
- Calculate the total calories in a dish
public void test7(a) {
Integer sum = menu.stream()
.collect(summingInt(Dish::getCalories));
System.out.println(sum);
}
Copy the code
-
Connection string
The parameter is a delimiter and may not be passed
public void test8(a) {
String joinWords = menu.stream()
.map(Dish::getName)
.collect(joining("... ""));
System.out.println(joinWords);
}
Copy the code
-
grouping
Customize a grouping method:
private CaloricLevel getCaloricLevel(Dish dish) { if (dish.getCalories() <= 400) { return CaloricLevel.DIET; } else if (dish.getCalories() <= 700) { return CaloricLevel.NORMAL; } else { returnCaloricLevel.FAT; }}Copy the code
- Group dishes by category
public void test3(a) { Map<CaloricLevel, List<Dish>> collect = menu.stream().collect( groupingBy(this::getCaloricLevel) ); } Copy the code
- Multistage grouping
public void test4(a) { Map<Dish.Type, Map<CaloricLevel, List<Dish>>> collect = menu.stream() .collect( groupingBy( Dish::getType, groupingBy( this::getCaloricLevel ) ) ); } Copy the code
-
You convert the results in the collector to another type and you group the dishes by category, and you take out the most caloric dishes in each group
collectingAndThen
public void test9(a) {
Map<Dish.Type, Dish> mostCaloricByType = menu.stream()
.collect(
groupingBy(
Dish::getType,
collectingAndThen(
maxBy(comparingInt(Dish::getCalories)),
Optional::get)));
}
Copy the code
partition
Partitioning is a special case of grouping and returns only Boolean values,
- Separate dishes according to meat and vegetables
public void test10(a){
Map<Boolean, List<Dish>> partitionMenu = menu.stream()
.collect(
partitioningBy(Dish::isVegetarian)
);
}
Copy the code
The Collectors class commonly uses the static factory method
The factory method | The return type | instructions |
---|---|---|
toList |
List<T> |
Collect all the items into a List |
toSet |
Set<T> |
Collect all items into a Set |
toCollection |
Collection<T> |
Collect all items into a collection created by a given provider |
counting |
Long |
Count the number of elements in the stream |
summingInt |
Integer |
The sum of an integer property in the stream |
averageingInt |
Double |
Returns the average value of the Integer items in the stream |
summarizingInt |
IntSummaryStatistics |
Collect statistics on item Integer attributes in the stream, such as maximum, minimum, and average |
joining |
String |
Concatenate the string generated by calling the toString method for each item in the stream |
maxBy |
Optional<T> |
A report selects the largest element Optional in the stream for the given comparator, or option.empty () if the stream is empty. |
reducing |
The type generated by the specification |
The iteration |
collectingAndThen |
The return value type of the conversion function | Wrap another collector and apply conversion functions to its results |
groupingBy |
Map<K,List<T>> |
grouping |
partitioningBy |
Map<Boolean,List<T>> |
partition |
The Collector interface
public interface Collector<T.A.R> {
/** * Creates a new container result */
Supplier<A> supplier(a);
/** * adds the element to the result container */
BiConsumer<A, T> accumulator(a);
/** * merges the two streams into one */
BinaryOperator<A> combiner(a);
/** * Apply the final transformation */ to the result container
Function<A, R> finisher(a);
/** * defines the behavior of the collector, whether streams can be specified in parallel. And those optimized hints, enumerations of three items * UNORDERED----- Protocol results are not affected by the order of traversal and accumulation in the project * CONCURRENT---- can be called from multiple threads simultaneously, The collector can parallel the protocol stream * IDENTITY_FINISH----- accumulator A converts unchecked to the result R is safe */
Set<Characteristics> characteristics(a);
}
Copy the code
Parallel computing
Parallel computing framework in jdk1.7ForkJoin
This framework uses the classic algorithm —- divide-and-conquer algorithm, the task is divided into several sub-tasks, and then by the multi-thread parallel execution of sub-tasks, the default number of threads open by the NUMBER of CPU cores available to determine.
Demo: parallel computation adds up from 1 to N
public class ForkJoinSumCalculator extends java.util.concurrent.RecursiveTask<Long> {
private final long[] numbers;
/** * The start and end positions of the array processed by the subtask */
private final int start;
private final int end;
/** * Array size that does not divide tasks into subtasks */
public static final long THRESHOLD = 10 _000;
private ForkJoinSumCalculator(long[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
public ForkJoinSumCalculator(long[] numbers){
this(numbers,0,numbers.length);
}
@Override
protected Long compute(a) {
int length = end - start;
if (length <= THRESHOLD) {
// If the size is less than or equal to the threshold, compute the results in order
return computeSequentially();
}
ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2);
// Another ForkJoinPool thread is used to execute the newly created subtask asynchronously
leftTask.fork();
ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end);
Long rightResult = rightTask.compute();
Long leftResult = leftTask.join();
return rightResult + leftResult;
}
private Long computeSequentially(a) {
long sum = 0;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
public static void main(String[] args) {
long[] numbers = LongStream.rangeClosed(1.1000000).toArray();
ForkJoinSumCalculator calculator = new ForkJoinSumCalculator(numbers);
Long invoke = newForkJoinPool().invoke(calculator); System.out.println(invoke); }}Copy the code
Work stealing
If we need to do a big task, we can put this task division for a number of mutually dependent child tasks, in order to reduce the competition between threads, then put these subtasks are different in the queue, and create a separate thread for each queue to perform the tasks in the queue, thread and queue one-to-one correspondence, For example, thread A handles tasks in queue A. However, some threads finish tasks in their queue first, while others have tasks in their queue. Instead of waiting, a finished thread can help another thread, so it steals a task from another thread’s queue to execute. In order to reduce the contention between the stolen thread and the stolen thread, a double-endian queue is usually used. The stolen thread always takes the task from the head of the double-endian queue, while the stolen thread always takes the task from the tail of the double-endian queue.
Jdk1.8 Spliterator
public interface Spliterator<T> {
boolean tryAdvance(Consumer<? super T> action);
Spliterator<T> trySplit(a);
long estimateSize(a);
int characteristics(a);
}
Copy the code
-
T is the type to iterate over the Spliterator element.
-
The tryAdvance method behaves like a normal Iterator
-
TrySplit divides some elements into a second Spliterator and lets the two process them in parallel
-
EstimateSize estimates how many elements are left to iterate over
-
Characteristics returns an int that represents the encoding of Spliterator’s own feature set
The appendix
Recommended reading: github.com/winterbe/ja…