Functional programming
OO (Object Oriented) is abstract data, FP (functional programming) is abstract behavior.
In Java 8 In action, the concept of parameterizing behavior is similar to this abstract behavior.
Lambda expressions
Basic syntax:
- Parameters.
- One argument, no parentheses required
(a)
; For more than two parameters, use parentheses(a)
Package parameters. - No arguments, use parentheses
(a)
Represents an empty parameter list.
- One argument, no parentheses required
- Then,
->
, can be regarded as “output”. ->
Everything after that is the method body.- Single line does not require {} wrap; Multiple lines require {} wrapping.
/ / no parameters
() -> System.out.println("hello")
/ / a single parameter
(a) -> System.out.println(a + "hello")
/ / parameters
(a,b) -> System.out.println(a + b + "hello")
// Multi-line method body
(a,b) -> {
System.out.println(a + b + "hello");
return a + b;
}
Copy the code
Method references
Class or object name :: Method name
Functional interface
Java 8 introduced the java.util. Function package. The interface in the package is the target type for Lambda expressions and method references. Each interface contains only one abstract method, called a functional method.
The package creates a complete set of target interfaces, freeing us from the need to define our own interfaces in general.
Use the @functionalInterface annotation to indicate that the interface is functional and force a check that only one abstract method can exist within the interface.
Function basic command rules:
-
If you only deal with objects (non-basic types), names are Function, Consumer, Predicate, Supplier, and so on. Parameter types are added via generics.
This is the base type, and there are almost all variations of it.
-
If the receive parameter is a primitive type, it is represented by the first part of the name. Examples include LongConsumer, DoubleFunction, IntPredicate, etc., except for the Supplier interface that returns the base type.
-
If the return value is a primitive type, it is represented by To, such as ToLongFunction
and IntToLongFunction.
-
If the return value type is the same as the parameter type, it indicates an operator: UnaryOperator is used for a single argument and BinaryOperator is used for two arguments.
-
If you take two parameters and return Boolean values, it’s a Predicate.
-
If the two parameters received are of different types, there is a Bi in the name.
The only reason to use basic types is to improve performance by avoiding automatic boxing and unboxing during passing parameters and returning results.
Higher-order functions
Functions that consume or produce functions.
// Just call Function by another name
interface FuncSS extends Function<String.String> {}
public class ProduceFunction {
Produce () is called a higher-order function
static FuncSS produce(a) {
return s -> s.toLowerCase(); // Return a function
}
public static void main(String[] args) {
FuncSS f = produce();
System.out.println(f.apply("YELLING")); }}Copy the code
closure
I don’t know what closure is for…
Function composition
“Function Composition” means “a combination of functions into a new Function”.
The common methods for composing are andThen(), compose(), and(), or(), and so on.
Currization and partial evaluation
Convert a multi-parameter function into a series of single-parameter functions. That’s not clear either.
public class CurryingAndPartials {
// Uncorrified:
static String uncurried(String a, String b) {
return a + b;
}
public static void main(String[] args) {
// Currified function:
Function<String, Function<String, String>> sum =
a -> b -> a + b; // The second argument is another function.
// Output Hi Ho
System.out.println(uncurried("Hi "."Ho"));
Function<String, String> hi = sum.apply("Hi "); / / [2]
// Output Hi Ho
System.out.println(hi.apply("Ho"));
// Some applications:
Function<String, String> sumHi = sum.apply("Hup ");
// Hup Ho
System.out.println(sumHi.apply("Ho"));
// Hup Hey
System.out.println(sumHi.apply("Hey")); }}Copy the code
Streaming programming
Collections optimize the storage of objects, while streams are concerned with the processing of objects.
Flow to create
-
Stream.of()
Stream<Integer> stream = Stream.of(1.2.3.4); Copy the code
-
Collection calls stream()
List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); Copy the code
-
Random number stream
Random has also added methods to generate streams.
Stream<Integer> stream2 = new Random(50).ints().boxed(); Copy the code
-
Integer sequence flow
IntStream stream3 = IntStream.range(1, 10); Copy the code
-
generate()
@FunctionalInterface public interface Supplier<T> { T get(a); } public class Generator implements Supplier<String> { Random rand = new Random(47); char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); // Implement the method of functional interface public String get(a) { return "" + letters[rand.nextInt(letters.length)]; } public static void main(String[] args) { // Pass in a provider-type interface String word = Stream.generate(new Generator()) .limit(30) .collect(Collectors.joining()); System.out.println(word); }}Copy the code
-
iterate()
The first argument to the Stream produced by iterate() is the seed, which is then passed to the second argument (the second argument is a method). The result, stored as the first argument on the next call to iterate().
Public class Fibonacci {int x = 1; Stream
numbers() { return Stream.iterate(0, i -> { int result = x + i; x = i; return result; }); }} Copy the code -
The builder pattern of flows
Stream.Builder<Integer> builder = Stream.builder(); builder.add(1).add(2).add(3); Stream<Integer> stream4 = builder.build();Copy the code
-
Arrays
String[] arrays = new String[] {"1"."2"."3"}; Stream<String> stream5 = Stream.of(args);Copy the code
-
Regular expression
String str = "a.b.c,f"; String s = Pattern.compile("[?] +") .splitAsStream(str) .map(a -> a + "") .collect(Collectors.joining()); System.out.println(s);Copy the code
In the middle of operation
debug
The peek() operation is intended to aid debugging by receiving a Consumer functional interface.
The sorting
sorted()
Stream<Integer> stream2 = new Random(50).ints(10.1000).boxed(); stream2 .skip(10) .limit(10) .sorted(Comparator.comparing(Integer::intValue)) .map(a -> a + "") .forEach(System.out::print);// 18 105 132 147 192 405 480 602 760 892
Copy the code
remove
There are two ways to remove elements, de-duplication and filtering.
-
Distinct () : Eliminates duplicate elements from a stream.
Stream<Integer> stream = Stream.of(1.2.3.4.2.3); List<Integer> collect = stream.distinct().peek(e -> System.out.println(e)).collect(Collectors.toList());// 1, 2, 3, 4 Copy the code
-
Filter (Predicate) : The Predicate () is true and preserves elements.
Stream<Integer> stream = Stream.of(1.2.3.4.2.3); List<Integer> collect1 = stream.filter(a -> a.equals(2)).peek(e -> System.out.println(e)).collect(Collectors.toList());2 / / 2 Copy the code
function
map(Function)
: applies the function operation to the elements of the input stream and passes the return value to the output stream.mapToInt(ToIntFunction)
: Same operation as above, but the result isIntStream
.mapToLong(ToLongFunction)
: Same operation as above, but the result isLongStream
.mapToDouble(ToDoubleFunction)
: Same operation as above, but the result isDoubleStream
.
Stream<Integer> stream = Stream.of(1.2.3.4.2.3); String collect = stream.map(a -> { String aStr = a +""; aStr += "^_^"; returnaStr; }).collect(Collectors.joining("")); System.out.println(collect);// 1^_^ 2^_^ 3^_^ 4^_^ 2^_^ 3^_^
Copy the code
Combination of flow
To combine multiple streams into a single stream, also called a flattened stream.
FlatMap () does two things: it applies the stream-generating function to each element (the same as map() does), and then flattens each stream into elements, so that it ends up producing only elements.
FlatMap (Function) : Used when Function generates a stream.
There are three other methods, similar to the other three of map().
. / / this is access to flow in the flow Stream of (1, 2, 3, 4). The map (a - > Stream) of (a + a + "a", "b", a + "c")). The forEach (System. Out: : println); //java.util.stream.ReferencePipeline$Head@6a41eaa2//java.util.stream.ReferencePipeline$Head@7cd62f43//java.util.stream.R EferencePipeline $Head @ 6 d4b1c02 / / Java. Util. Stream. ReferencePipeline $Head @ 6093 dd95 stream. Of (1, 2, 3, 4). FlatMap (a - > Stream.of(a+"a",a+"b",a+"c")) .forEach(System.out::println); //1a 1b 1c 2a 2b 2c 3a 3b 3c 4a 4b 4c
Copy the code
Optional class
Some stream operations return Optional objects to avoid null pointer exceptions.
findFirst()
Returns an object containing the first elementOptionalObject that returns if the stream is emptyOptional.empty
findAny()
Object containing any elementOptionalObject that returns if the stream is emptyOptional.empty
max()
和min()
Returns a value that contains either a maximum or minimum valueOptionalObject that returns if the stream is emptyOptional.empty
Optional convenience function
ifPresent(Consumer)
: called when the value existsConsumerOtherwise, do nothing.orElse(otherObject)
: Returns the value if it exists, otherwiseotherObject.orElseGet(Supplier)
: returns the value if it exists, otherwiseSupplierThe function generates a substitute object.orElseThrow(Supplier)
: returns if the value exists, otherwiseSupplierThe function generates an exception.
Optional creation method
empty()
: Generates a nullOptional.of(value)
: wraps a non-null value toOptionalIn the water.ofNullable(value)
: For a value that may be null, automatically generated if nullOptional.emptyOtherwise, wrap the value inOptionalIn the.
Optional object operation
filter(Predicate)
:OptionalContent application inPredicateAnd returns the result. If the content is not satisfiedPredicateAnd returns an emptyOptional. ifOptionalIf it is already null, return null directlyOptional 。map(Function)
If:OptionalNot null, the content executes the method and returns the result. Otherwise it just returnsOptional.empty.flatMap(Function)
With:map()
, not toOptional
Encapsulation.
Optional flow
// create Optional Stream Stream = stream.of (1,null,2,3).map(signal -> optional.ofnullable (signal)); // Use Optional stream stream.limit (10).filter(Optional::isPresent).map(Optional::get).foreach (system.out ::println);
Copy the code
Terminal operation
The stream operation completes after the terminal operation is performed.
An array of
toArray()
: Converts the flow to an array of the appropriate type.toArray(generator)
: Generates arrays of custom types in special cases.
cycle
forEach(Consumer)
Such as commonSystem.out::println
As aConsumerFunction.forEachOrdered(Consumer)
: ensure thatforEach
Operate in the original stream order.
Parallel () : Enables parallel operation of multiple processors. This works by dividing a stream into multiple (usually CPU cores) and performing operations on different processors.
A collection of
collect(Collector)
Use:CollectorCollect the flow elements into the result set.collect(Supplier, BiConsumer, BiConsumer)
: Same as above, the first parameterSupplierCreates a new result set, second parameterBiConsumerCollects the next element into the result set, the third parameterBiConsumerUse to combine two result sets.
combination
reduce(BinaryOperator)
Use:BinaryOperatorTo combine all the elements in the stream. Because the stream may be empty, its return value isOptional.reduce(identity, BinaryOperator)
: Same function as above, but useidentityAs the initial value of its composition. So if the stream is empty,identityThat’s the result.
matching
allMatch(Predicate)
: On the first false, the calculation is stopped.anyMatch(Predicate)
: The first true stops the computation.noneMatch(Predicate)
: If each element of the stream is supplied toPredicateIf both return false, the result returns true. Stop the calculation on the first true.
To find the
findFirst()
: returns the first stream elementOptionalReturns if the stream is emptyOptional.empty.findAny(
: Returns any stream elementOptionalReturns if the stream is emptyOptional.empty.
information
count()
: Number of elements in the stream.max(Comparator)
: According to incomingComparatorThe “maximum” element determined.min(Comparator)
: According to incomingComparatorThe “smallest” element determined.
Digital stream information
average()
: Takes the average value of the stream elements.max()
和min()
: No need for numerical flow operationsComparator.sum()
: sums all the stream elements.