Functional interface

Java built-in

Core interface sub interface

Public static void test1(){cost(8888, (m) -> system.out. println(" Cost: + m + "));}} public static void test1(){cost(8888, (m) -> system.out. println(" Cost: + m + ")); } public static void cost(double money,Consumer<Double> con){ con.accept(money); } public static void test2(){List<Integer> List = getNumList(8, () -> (int)(Math.random() * 100));} public static void test2(){List<Integer> List = getNumList(8, () -> (int)); for (Integer integer : list) { System.out.println(integer); Public static List<Integer> getNumList(int num,Supplier<Integer> sup){List<Integer> List = new ArrayList<>(); for (int i = 0; i < num; i++) { Integer n = sup.get(); list.add(n); } return list; } public static void test3(){String String = strHandler(String String = strHandler); (str) -> str.trim().substring(0, 5)); System.out.println(string); Public static String strHandler(String STR,Function<String, String> fun){return fun.apply(STR); } public static void test4(){List<String> List = Arrays.asList("hello","Lambda","ok"); List<String> strList = filterStr(list, (s) -> s.length() > 3); for (String string : strList) { System.out.println(string); Public static List<String> filterStr(List<String> List, List<String> List, List<String> List, Predicate<String> pre){ List<String> strList = new ArrayList<>(); for (String str : list) { if (pre.test(str)) { strList.add(str); } } return strList; }

Method references and constructor references

When you pass an operation to a Lambda body, you already have a method to implement it, and you can use a method reference! Implement the abstract method’s argument list, must be the same as the method reference method’s argument list! Method references: Use the “::” operator to separate the method name from the name of the object or class.

There are three main uses:

  • Object :: instance method
  • Class :: Static methods
  • Class :: instance method

Notes for use:

  • 1. The parameter list and return value type of the method called in the Lambda body should be consistent with the function list and return value type of the abstract method in the functional interface.
  • 2. If the first argument in the Lambda argument list is the instance method caller and the second argument is the instance method’s argument, className :: method can be used
@test public void test1(){printStream ps = System.out; Consumer<String> con = (str) -> ps.println(str); Con. Accept (" Hello World!" ); Consumer<String> con2 = ps::println; Con2. Accept (" Hello World!" ); Consumer<String> con3 = System.out::println; } @test public void test2(){Comparator<Integer> com = (x, y) ->, y); Comparator<Integer> com2 = Integer::compare; } @Test public void test3(){BiPredicate<String, String> BP = (X, Y) -> x.quals (Y); System.out.println(bp.test("abcde", "abcde")); BiPredicate<String, String> bp2 = String::equals; System.out.println(bp2.test("abc", "abc")); Function<Employee, String> fun = (e) ->; System.out.println(fun.apply(new Employee())); Function<Employee, String> fun2 = Employee::show; System.out.println(fun2.apply(new Employee())); }

Constructor reference:

  • The constructor argument list should be the same as the argument list for the abstract method in the interface, in the form of the class name ::new
  • Combined with a functional interface, it is automatically compatible with methods in a functional interface
public void test1(){
        Supplier<Employee> sup = () -> new Employee();
        Supplier<Employee> sup1 = Employee::new;

An array reference

  • Format: Type [] :: new
public void test1(){
        Function<Integer, String[]> fun = (args) -> new String[args];
        String[] strs = fun.apply(10);
        Function<Integer, String[]> fun1 = String[] :: new;
        String[] strs = fun1.apply(20);

Stream API

The Stream itself does not store the elements, does not change the source object, and returns a new Stream that holds the result. The operation is delayed. The Stream API provides an efficient and easy to use way to process data

The Stream API is provided in the following steps:

2. Intermediary operation 3. Terminate operation (terminal operation)

Create a Stream

Approach 1: The Collection interface in Java8 is extended. Provides two methods to get a stream

Default Stream ParallelStream () : ParallelStream () Note: Any implementation class or subinterface under the Collection interface can return a stream to the stream object via method

The stream() static method of Arrays in Java8 gets the array streams

Static Stream (T[] array) static Stream (T[] array) static Stream (T[] array

The static stream.of () method of the Stream class creates a Stream by displaying a value that can take any number of arguments

Public static Stream of (T… VALUES) : Returns a Stream using Stream Stream = stream. of(” a “, “b”, “c”)

Iterate () The static methods stream.iterate () and stream.generate () create an infinite Stream

Iterate public static Stream generate(Supplier s). Iterate public static Stream generate(Supplier s). Iterate public static Stream generate(final T seed, final UnaryOperator f).

Public void test1(){// ParallelStream () List<String bb0 List = new ArrayList<>(); Stream<String> stream =; / / 2. Through the static method in the Arrays stream flow () to obtain array Person [] persons = new Person [10]. Stream<Person> stream2 =; Stream.of("a","b","c"); stream. of("a","b","c"); // Iterate <Integer> Stream4 = Stream.iterate(0, (X) -> X + 2); stream4.limit(8).forEach(System.out :: println); Stream. Generate (() -> Math.random()).limit(6).foreach (System.out :: println); }

In the middle of operation

Screening and sectioning methods

  • Filter (Perticate p) – takes Lambda and excludes certain elements from the stream
  • DISTINCT () – Filter, removing duplicate elements by hashCode() and equals() of the elements generated by the stream
  • Limit (Long n) – Truncates the stream so that it does not exceed a given number of elements
  • Skip (Long n) — Skip (Long n) — Returns a stream that has discarded the first n elements. If there are fewer than n elements in the stream, returns an empty stream, complementary to limit(n)

Mapping method

  • Map (Function f) – takes a Function as an argument that will be applied to each element and will map it to a new element
  • FlatMap (Function f) – takes a Function as an argument, replaces each value in the stream with another stream, and then concatenates all streams into one stream
  • MapToDouble (todoubleFunction f) – takes as an argument a function that will be applied to each element, producing a new doubleStream
  • MapToInt (tointFunction f) – takes a function as an argument that will be applied to each element, producing a new IntStream
  • MapToLong (tolongFunction f) – takes a function as an argument that will be applied to each element, producing a new LongStream

Sorting method

  • Sorted () – Generates a new stream and sorts it in natural order
  • Sorted ( – Generates a new stream that customizes sorted by Comparator order
/** * public class TestArray2 {List< persondb persons = Array. asList(new persondb (2, "persondb "," persondb ", "persondb "," persondb ", "persondb "," persondb ", "persondb "," persondb ", "persondb "," persondb ", "persondb "," persondb ", "persondb"), New Person(1, "Person ", 33), new Person(2," Person ", 24), new Person(3, "Person ", 65), new Person(4," Person ", 26), new Person(4, "Person ", 26), 26), new Person(5, "Person ", 27)); // internal iteration, @test public void test1(){Stream<Person> Stream = ().filter((e) -> {Stream<Person> Stream = ().filter((e) -> { System.out.println(" Intermediate operation of Stream "); return e.getAge() > 25; }); ForEach (System.out :: println); stream. ForEach (System.out :: println) } @test public void test2(){Iterator<Person> Iterator = Persons.iterator (); while (iterator.hasNext()) { System.out.println(; }} public void test3(){ ().filter((E) -> {System.out.println());} public void test3(){ ().filter((E) ->; // return testetage (); }) .limit(2) .forEach(System.out :: println); } @Test public void test4(){ ().filter((E) -> E.getage () > 23) @Test public void test4(){ ().filter((E) -> E.getage () > 23) .skip(2) .distinct() .forEach(System.out :: println); } / / map @ Test public void test5 () {a List < String > List = Arrays. The asList (" a ", "bb", "c", "d", "e"); -> str.toUpperCase()) .forEach(System.out :: println); System.out.println("---------------"); :: getName)).forEach(System.out :: println); System.out.println("---------------"); Stream<Stream<Character>> stream = .map(TestSteamAPI2 :: filterCharacter); stream.forEach((s) -> { s.forEach(System.out :: println); }); System.out.println("-----------------"); //flatMap Stream<Character> stream2 = .flatMap(TestSteamAPI2 :: filterCharacter); stream2.forEach(System.out :: println); Public static Stream<Character bb1 filterCharacter(String STR){List<Character bb1 List = new ArrayList< bb2 (); for (Character character : str.toCharArray()) { list.add(character); } return; } @Test public void test6(){List<String BB0 List = Arrays.asList(" Arrays.b "," Arrays.c "," Arrays.b "," Arrays.b "," Arrays.b "," Arrays.b "," Arrays.b "); ().sorted();; System.out.println("------------"); .sorted((p1,p2) -> { if (p1.getAge() == p2.getAge()) { return p1.getName().compareTo(p2.getName()); } else { return p1.getAge() - p2.getAge(); } }).forEach(System.out :: println); }}

Termination of operations

Find and match methods

  • AllMatch (Perticate p) – checks to see if all elements match
  • AnyMatch (Perticate p) – checks if at least one element matches
  • NoneMatch (Perticate p) — checks if there are no matching elements
  • FindFirst () – returns the first element
  • FindAny () – Returns any element in the current stream
  • Count () – Returns the total number of elements in the stream
  • MAX (Comparator C) – Returns the maximum value in the stream
  • Min (Comparator C) – Returns the minimum value in the stream
  • ForEach (Consumer C) — Internal Iteration (using the Collection interface requires the user to do an iteration to become an external iteration)

Reduction method

  • Reduce (T-Identity, BinaryOperator B) – You can combine the elements in the stream repeatedly, resulting ina value that returns T
  • Reduce (BinaryOperator B) – You can combine elements ina stream repeatedly to get a value that returns Optional

Collection methods

  • Collect (Collector C) – A way to convert a Stream to another form and receive an implementation of a Collector interface for summarizing elements in a Stream
/ * * * Stream API terminates operation * / public class TestSteamAPI3 {List < Person > persons = Arrays. The asList (new Person (2, "four" money, 24,Status.YOUNG), new Person(1, "", 23,Status.YOUNG), new Person(2," ", 24,Status.YOUNG), new Person(3, ""," ", 65, status. OLD), new Person(4, "Zhao 6 ", 26, status. MIDDLE), new Person(4," Zhao 6 ", 56, status. OLD), new Person(5, "Chen 7 ", 27,Status.MIDDLE) ); @Test public void test1(){Boolean b = ().allMatch((e) -> E.E.Status ().equals(status.young)); System.out.println(b); boolean b2 = .anyMatch((e) -> e.getStatus().equals(Status.YOUNG)); System.out.println(b2); boolean b3 = .noneMatch((e) -> e.getStatus().equals(Status.MIDDLE)); System.out.println(b3); Optional<Person> op = .sorted((e1,e2) ->, e2.getAge())) .findFirst(); System.out.println(op.get()); Optional<Person> optional = .filter((e) -> e.getStatus().equals(Status.OLD)) .findAny(); System.out.println(optional.get()); } @test public void test2(){long Count = ().count(); System.out.println(count); Optional<Person> optional = .max((e1,e2) ->, e2.getId())); System.out.println(optional.get()); Optional<Integer> op = .map(Person :: getAge) .min(Integer :: compare); System.out.println(op.get()); } @test public void test3(){List<Integer> List = Arrays.asList(1,2,3,4,5,6,7,8); Integer sum = .reduce(0, (x,y) -> x + y); System.out.println(sum); System.out.println("------------"); Optional<Integer> optional = .map(Person :: getAge) .reduce(Integer :: sum); System.out.println(optional.get()); } @Test public void test4(){List<String> List = ().map(Person :: Person){List<String> List = ().map(Person :: Person); getName) .collect(Collectors.toList()); list.forEach(System.out :: println); System.out.println("------------"); Set<String> set = .map(Person :: getName) .collect(Collectors.toSet()); set.forEach(System.out :: println); System.out.println("------------"); HashSet<String> hashSet = .map(Person :: getName) .collect(Collectors.toCollection(HashSet :: new)); hashSet.forEach(System.out :: println); } @Test public void test5(){ Long count = .collect(Collectors.counting()); System.out.println(" total number ="+count); System.out.println("----------------"); Double avg = (). Collect (Person :: getAge); Println (" Average age ="+avg); System.out.println("---------------"); // Integer sum = (). Collect (Person :: getAge)); System.out.println(" age sum ="+sum); System.out.println("----------------"); // Optional<Person> Max = (). Collect ((e1,e2) -> GetAge (), e2.getAge()))); Println (" maximum age is "+max.get()); System.out.println("----------------"); // Optional<Person> min = (). Collect ((e1,e2) -> GetAge (), e2.getAge()))); System.out.println(" Minimum age is "+min.get()); } @test public void test6(){Map<Status, void test6(); List<Person>> map = .collect(Collectors.groupingBy(Person :: getStatus)); // System.out.println(map); } @test public void test7(){Map<Status, Map<String, List<Person>>> map = .collect(Collectors.groupingBy(Person :: GetStatus,Collectors. GroupingBy ((E) -> {if (Equetid ()%2 == 1) {return "single "; } else {return "double "; }}))); System.out.println(map); } // partition @test public void test8(){Map<Boolean, List<Person>> map = .collect(Collectors.partitioningBy((e) -> e.getAge() > 30)); System.out.println(map); } //IntSummaryStatistics @Test public void test9(){ IntSummaryStatistics iss = .collect(Collectors.summarizingInt(Person :: getAge)); System.out.println(iss.getSum()); System.out.println(iss.getAverage()); System.out.println(iss.getMax()); } @Test public void test10(){ String str = .map(Person :: GetName). Collect (Collectors. Joining (", ", "staff list:", "such as")); System.out.println(str); }}

Parallel streaming versus serial

In order to adapt to the current era of multi-core machines and improve the CPU and memory utilization of the system, the new stream package of JDK 1.8 also provides parallel and serial operation streams for collection operations. Parallel streaming means cutting content into blocks of data and using multiple threads to process the contents of each block separately. The Stream API states that you can switch between parallel and serial streams using parallel() and sequential() methods. JDK 1.8 parallel streams use the fork/join framework for parallel operations Note: Using parallel streams is not necessarily efficient, as it also takes time for the JVM to slice the data and switch threads. So the smaller the data, the faster the serial operation; The larger the amount of data, the better the parallel operation

/* public class ForkJoincalculate extends RecursiveTask<Long>{private static final Long serialVersionUID = 1L; private long start; private long end; private static final long THRESHOLD = 10000; public ForkJoinCalculate() { } public ForkJoinCalculate(long start, long end) { this.start = start; this.end = end; } @Override protected Long compute() { long length = end - start ; if (length <= THRESHOLD) { long sum = 0; for (long i = start; i <= end; i++) { sum += i; } return sum; }else { long middle = (start + end) / 2; ForkJoinCalculate left = new ForkJoinCalculate(); left.fork(); ForkJoinCalculate = new ForkJoinCalculate(); forkJoinCalculate (); right.fork(); return left.join() + right.join(); @test public void test1(){@test public void test1(){@test public void test1(){@test public void test1(){@test public void test1(); ForkJoinPool pool = new ForkJoinPool(); ForkJoinTask<Long> Task = new ForkJoinCalculate(0, 000,000L); Long sum = pool.invoke(task); System.out.println(sum); Instant end =; System.out.println(Duration.between(start,end).toMillis()); } /** * for loop */ @test public void test2(){InstantStart =; long sum = 0L; for (long i = 0; i <= 10000000000L; i++) { sum += i; } System.out.println(sum); Instant end =; System.out.println(Duration.between(start, end).toMillis()); } /** * @test public void test3(){InstantStart =; LongStream.rangeClosed(0, 10000000000L) .parallel() .reduce(0,Long :: sum); Instant end =; System.out.println(Duration.between(start, end).toMillis()); }}

Default and static methods in the interface

// Prior to JDK 1.8, variables in interfaces must be public static final, methods must be public, etc. Public interface myService {public static final String KEY = "Hello World "; String key = "hello world"; public abstract void sayHello(); void sayHi(); } // This has changed since JDK 1.8, when the JDK added default and static methods to the interface. Public interface myService {/* static void method1(){System.out.println(); public interface myService {/* static void method1(); MyService.method1()"); } /* default method */ default void method2(){System.out.println(" This is the default method called on myService instance.method2()"); }}

Note: Since Java supports a single implementation class that can implement multiple interfaces, what if the same static and default methods exist in multiple interfaces? If you have static methods in two interfaces that are identical, and an implementation class implements both interfaces, no error will be generated, because JDK8 can only call static methods in the interface through the interface class, so it is indistinguishable to the compiler. But if identical default methods are defined in two interfaces, and an implementation class implements both interfaces, then the default method must be overridden in the implementation class, or the compilation fails

New time and date API

Disadvantages of the old date API

  • Since jdk1.1 created, Date processing without specification, in multiple packages such as Java. Util. Date, Java. Text. The text. The DateFormat, etc
  • The existing date API has thread-safety issues with multiple threads (circumvented by methods such as ThreadLocal)

Introduction to the new date API

Advantages The new date API is thread-safe, unified within java.time and its subpackages, with a separation of concerns, and a class classification of machine-used timestamps and human-readable dates

  • Java. Time and its subpackages

    • Java.time package: This is the base package for the new Java date/time API. All the major base classes are part of this package, such as LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration, and so on. All of these classes are immutable and thread-safe, and in the vast majority of cases, they effectively handle some common requirements
    • Java.time.chrono package: This package defines some generic APIs for non-ISO calendar systems. We can extend the AbstractChronology class to create our own calendar system
    • The java.time. Format package: This package contains classes that format and parse date and time objects. In most cases, we should not use them directly because the corresponding classes in the java.time package already provide formatting and parsing methods
    • Java.time. temporal package: This package contains temporal objects that we can use to find a specific date or time about a date/time object, for example, to find the first or last day of a month. You can easily recognize these methods because they all have the “withXXX” format
    • The package: This package contains classes that support different time zones and related rules
Public class LocalDateTimeTest {/ * localDate/localtime/localdateTime * / @ Test public void test1 () {/ / get the current date/time LocalDateTime ldt =; System.out.println(ldt); LocalDateTime ldt1 = localDateTime. Of (2020,12,30,1,2,3); System.out.println(ldt1); // System.out.println(ldt.plusYears(2)); // Date specified - March localdateTime ldt2 = ldt.minusmonths (3); System.out.println(ldt2); System.out.println(ldt.getYear()); // Get the year System.out.println( ()); // @test public void test2(){; @test public void test2(){; Println (ins+",,,"+ins. GetEpochSecond ()); OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8)); // System. Out.println (odt); Instant ins1 = Instant.ofEpochSecond(5); System.out.println(ins1); // 1970-01-01t00:00:05z offset from Unix year 5S} /** * Duration: Calculates two "time" intervals * Period: * * @test public void test3() throws InterruptedException {InstantIns1 =; Thread.sleep(1000); Instant ins2 =; Println (" time between(ins1,ins2) +Duration. Between (ins1,ins2)); PT1S localDate date1 = localDate. Of (2011,3,5); LocalDate date2 =; Period pe = Period.between(date1,date2); System. Out. Println (" the interval of two dates for - "" + PE +", and interval for - "" + PE. GetYears ()); /* TemporalAdjuster */ @Test public void test4(){LocalDateTime LDT =; System.out.println(" What is the date of the day --> "+ldt.getDayOfMonth()); Println (" What's next Sunday? "+ ldt.with(TemporalAdjusters. Next (dayofweek.Sunday))); // Customize next business day localDateTime dateTime = ldt.with((Temporal)->{localDateTime lt = ldt.with((Temporal)->{localDateTime lt = LDT (LocalDateTime)temporal; DayOfWeek dow = lt.getDayOfWeek(); if(DayOfWeek.FRIDAY.equals(dow)){ return lt.plusDays(3); }else if(DayOfWeek.SATURDAY.equals(dow)){ return lt.plusDays(2); }else{ return lt.plusDays(1); }}); System.out.println(" Next business day will be -- "+dateTime); @test public void test5(){@test public void test5(){@test public void test5(){@test public void test5(){@test public void test5(){@test public void test5(); , of course, also can use the default format of the specified DateTimeFormatter format = DateTimeFormatter. OfPattern (" MM - dd yyyy - HH: MM: ss "); LocalDateTime ldt =; System.out.println(format.format(ldt)); Parse ("2017-11-12 23:10:05",format); parse("2017-11-12 23:10:05",format); System.out.println(ldt2); //2017-11-12T23:10:05} /* ZonedDate, ZonedTime, ZonedDateTime */ @Test public void test6(){LocalDateTime LDT1 ="Asia/Shanghai")); //Asia/ Shanghai Time-> 2017-03-23T22:57:21.084 system.out. println("Asia/ Shanghai Time-> "+ LDT1); ZonedDateTime zdt ="America/Marigot")); System.out.println(zdt); / / the T10:2017-03-23 59:43. 708-04:00 America/Marigot System. Out. Println (ZDT. ToLocalDateTime ()); : / / 2017-03-23 T11 00:49. 177 is converted to the current time zone System. Out. The println (" -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "); / / get time zone ID list / / ZoneId getAvailableZoneIds () stream (). The forEach (System. Out: : println); }}


The Optional<T> class is a container class that can hold a value of type T to indicate that it exists, or it can be NULL to indicate that it does not. This is a container object that can be NULL. The isPresent() method returns true if the value isPresent, and a call to get() returns the object

API for creating Optional class objects

  • Optional.of(T t):

    • Create an Optional instance for a value that is not NULL. T cannot be null
// Call the factory method to create an Optional instance Optional<String> name = option. of(" Tom "); // Throw NullPointerException. Optional<String bb0 someNull = option.of (null);

Optional. Ofnullable (T T): More commonly used

  • Create an Optional instance where t can be null
// create an Optional instance with no value Optional Empty = Optional. OfNullable (NULL);


  • Create an empty Optional instance

Determine whether the Optional container contains an object

  • boolean isPresent():

    • It’s easy to understand that the value returns true if it exists and false otherwise

void ifPresent(Consumer<? super T> ):

  • If there is a value, the implementation code for the Consumer interface is executed, and the value is passed to it as an argument
// The ifPresent method takes a lambda expression as an argument. // The lambda expression calls consumer on the value Optional. name.ifPresent((value) -> { System.out.println("The length of the value is: " + value.length()); });

T orElse(T other): More commonly used

  • Returns a value if any, otherwise the other value specified

T orElseGet(Suppliper<? entend X> other):

  • Returns a value if there is one, otherwise returns the object provided by the Supplier interface implementation
// OrelseGet is similar to the Orelse method, except that Orelse passes in the default value. OrelseGet can take a lambda expression to generate the default value. System.out.println(empty.orElseGet(() -> "Default Value")); System.out.println(name.orElseGet(() -> "Default Value"));

T orElseThrow(Suppliper<? entend X> exceptionSuppliper):

  • Returns a value if there is, otherwise throws an exception provided by the Supplier interface implementation
Try {// ORelseThrow is similar to ORelse. And returns the default value is different, / / orElseThrow throws lambda expressions or method to generate abnormal empty. OrElseThrow (ValueAbsentException: : new); } catch (Throwable ex) {// No value present in the Optional instance system.out. println(ex.getMessage()); }