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:

  1. 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.
  2. Then,->, can be regarded as “output”.
  3. ->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:

  1. 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.

  2. 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.

  3. If the return value is a primitive type, it is represented by To, such as ToLongFunction

    and IntToLongFunction.

  4. 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.

  5. If you take two parameters and return Boolean values, it’s a Predicate.

  6. 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

  1. Stream.of()

    Stream<Integer> stream = Stream.of(1.2.3.4);
    Copy the code
  2. Collection calls stream()

    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();
    Copy the code
  3. Random number stream

    Random has also added methods to generate streams.

    Stream<Integer> stream2 = new Random(50).ints().boxed();
    Copy the code
  4. Integer sequence flow

    IntStream stream3 = IntStream.range(1, 10);
    Copy the code
  5. 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
  6. 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
  7. 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
  8. Arrays

    String[] arrays = new String[] {"1"."2"."3"}; Stream<String> stream5 = Stream.of(args);Copy the code
  9. 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 toOptionalEncapsulation.

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::printlnAs aConsumerFunction.
  • forEachOrdered(Consumer): ensure thatforEachOperate 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.