Day _27 Lambda expressions, functional interfaces

Keywords: JavaEE

1.Lambda

1.1 general

Lambda expression is a function without a name, also known as closure. It is the most important new feature released by Java 8.

It is essentially an anonymous inner class or a piece of code that can be passed.

And the arrow function

1.2 why use Lambda expressions

Lambda expression is a shorthand for an anonymous inner class

It makes the program more concise and clear, and the programming efficiency has been improved

one point three   Comparison with anonymous inner classes

 

  1.4 grammatical structure

Optional type declaration: there is no need to declare parameter types, and the compiler can uniformly identify parameter values.

                    

Optional parameter parentheses: one parameter does not need to define parentheses, but multiple parameters need to define parentheses.

                    

Optional curly braces: if the body contains a statement, curly braces are not required.

If you don't write {}   return cannot be written   Semicolon cannot be written

                    

Optional return keyword: if the body has only one expression return value, the compiler will automatically return the value. Braces need to specify that the expression returns a value

     If there is only one statement and it is a return value statement, you can not write return or {}  

     If you write {}   You must write return and;

    If there are multiple statements, you must write {}   return and;   Must also write

  1.5 cases

1 does not require parameters, and the return value is 5

()-> 5

2 receives a parameter (numeric type) and returns twice its value  

x -> x*2

3 accepts 2 parameters (numbers) and returns their difference  

(x,y)-> x-y

1.6 practice

public static void main(String[] args) {
	//create object
	List <Integer>list=new ArrayList<Integer>();
	list.add(1);
	list.add(2);
	list.add(3);
	//Conventional writing
	//for(Integer integer:list){
		//System.out.println(integer);
	//}
	//Anonymous Inner Class 
	//list.forEach(new Consumer<Integer>(){
		//@Override
		//public void accept(Integer t){
		//System.out.println(t);
		//}
	//});
	//lambda writing
	list.forEach(x->System.out.println(x));
}

public static void main(String[] args) {
		//Create a collection object
		List<Integer>list=new ArrayList<Integer>();
		//Call the add method to add data
		list.add(11);
		list.add(2);
		list.add(3);
		//Call method sorting
		Collections.sort(list,new Comparator<Integer>(){
		@Override
		public int compare(Integer o1,Integer o2){
			return o2-o1;
		}
		});
		Collection.sort(list,(x,y)->y-x);
		System.out.println(list);
	}
}
class B{
	@Override 
	public boolean equals(Object obj){
		return false;
	}

2. Functional interface

two point one   introduce

It is called Functional Interface in English

         

Its essence is an interface with one and only one abstract method, but it can have multiple non abstract methods.

         

The core goal is to provide better support for the use of Lambda expressions and further achieve the goal of functional programming. The programming efficiency can be greatly improved by using functional programming.

         

It can be implicitly converted to a lambda expression.

2.2 features

  A functional interface is an interface that formulates only one abstract method

Can contain one or more static or default methods

         

The special annotation, @ FunctionalInterface, checks whether it is a functional interface or not

If there are two or more abstract methods, they cannot be used as functional interfaces, and the @ functional interface annotation cannot be added

If there is only one abstract method, the @ functional interface annotation can be used as a functional interface with or without it

two point three   code implementation

No parameter condition

public class FunInterface_01 {

    // Custom static method to receive interface object

    public static void call(MyFunctionInter func) {

        // Calling member methods within an interface

        func.printMessage();

    }



    public static void main(String[] args) {

        // The first call: directly call the custom call method and pass in the function

        FunInterface_01.call(() -> {

            System.out.println("HelloWorld!!!");

        });



        // The second call: first create a function object, similar to the internal class object that implements the interface

        MyFunctionInter inter = () -> {

            System.out.println("HelloWorld2!!!!");

        };

        // Call the method of this implementation

        inter.printMessage();

    }

}

// Functional interface

@FunctionalInterface

interface MyFunctionInter {

    void printMessage();

}



Demo example:_01_FunInterface.java

With participation

public class FunInterface_02 {

    // Custom static method to receive interface object

    public static void call(MyFunctionInter_02 func, String message) {

        // Calling member methods within an interface

        func.printMessage(message);

    }



    public static void main(String[] args) {

        // Call the data to be passed

        String message = "Parametric functional interface call!!!";



        // The first call: directly call the custom call method, pass in the function, and pass in the data

        FunInterface_02.call((str) -> {

            System.out.println(str);

        }, message);



        // The second call: first create a function object, similar to the internal class object that implements the interface

        MyFunctionInter_02 inter = (str) -> {

            System.out.println(str);

        };

        // Call the method of this implementation

        inter.printMessage(message);

    }

}



// Functional interface

@FunctionalInterface

interface MyFunctionInter_02 {

    void printMessage(String message);

  two point four   JDK comes with common functional interfaces

2.4.1

public class _03_JdkOwn_01 {
	private static String getResult(Supplier<String> function) {
		return function.get();
	}

	public static void main(String[] args) {
		// 1
		String before = "Zhang San";
		String after = "Hello";
		// Concatenate two strings
		System.out.println(getResult(() -> before + after));

		// 2 / / create a Supplier container and declare it as_ 03_JdkOwn type
		// At this time, the construction method of the object is not called, that is, the object is not created
		Supplier<_03_JdkOwn_01> sup = _03_JdkOwn_01::new;
		_03_JdkOwn_01 jo1 = sup.get();
		_03_JdkOwn_01 jo2 = sup.get();

	}

	public _03_JdkOwn_01() {
		System.out.println("The construction method is executed");

Supplier < T > interface

Supplier < T > interface     Represents the result supplier, so there is a return value to obtain data

There is a get method for getting data

public class _03_JdkOwn_01 {
	private static String getResult(Supplier<String> function) {
		return function.get();
	}

	public static void main(String[] args) {
		// 1
		String before = "Zhang San";
		String after = "Hello";
		// Concatenate two strings
		System.out.println(getResult(() -> before + after));

		// 2 / / create a Supplier container and declare it as_ 03_JdkOwn type
		// At this time, the construction method of the object is not called, that is, the object is not created
		Supplier<_03_JdkOwn_01> sup = _03_JdkOwn_01::new;
		_03_JdkOwn_01 jo1 = sup.get();
		_03_JdkOwn_01 jo2 = sup.get();

	}

	public _03_JdkOwn_01() {
		System.out.println("The construction method is executed");

2.4.2consumer < T > interface

Consumer < T > interface     Consumer interface, so no return value is required

There is an accept(T) method, which is used to perform consumption operations. You can do any operation on a given parameter t

public class _04_JdkOwn_02 {
	private static void consumeResult(Consumer<String> function, String message) {
		function.accept(message);
	}

	public static void main(String[] args) {
		// Parameters passed
		String message = "Consume some content!!!";
		// Call method
		consumeResult(result -> {
			System.out.println(result);
		}, message);

2.4.3​​​​​​​   Function < T, R > interface

Function < T, R > interface   Represents a function that receives a parameter and produces a result

As the name suggests, it is a function operation

There is an R apply(T) method. There is no specific operation in the Function. The specific operation needs to be specified for it. Therefore, the specific result returned by apply depends on the incoming lambda expression

public class _05_JdkOwn_03 {
	// Function < parameter, return value >
	public static void convertType(Function<String, Integer> function,
			String str) {
		int num = function.apply(str);
		System.out.println(num);
	}

	public static void main(String[] args) {
		// Parameters passed
		String str = "123";
		// S indicates that parameters need to be passed. You can also write (s)
		convertType(s -> {
			int sInt = Integer.parseInt(s);
			return sInt;
		}, str);
	}

2.4.4 predict < T > interface

Predict < T > interface    Assertion interface

Just make some judgments, and the return value is boolean

There is a boolean test(T) method to verify whether the incoming data meets the judgment conditions and return the boolean type

public class _06_JdkOwn_04 {
	// Custom method, and Predicate receives String type
	public static void call(Predicate<String> predicate, String isOKMessage) {
		boolean isOK = predicate.test(isOKMessage);
		System.out.println("isOK Yes:" + isOK);
	}

	public static void main(String[] args) {
		// Parameters passed in
		String input = "ok";
		call((String message) -> {
			// Case insensitive comparison. If it is ok, it returns true; otherwise, it returns false
			if (message.equalsIgnoreCase("ok")) {
				return true;
			}
			return false;
		}, input);

  3. Method reference and constructor call

Object call member


object reference:Member's legal name
 * requirement:You need to select the corresponding functional interface according to the input and output parameters of the calling object method

public static void main(String[] args) {
	Integer i1=new Integer(123);
	//Conventional lambda writing
	Supplier<String>su=()->i1.toString();
	System.out.println(su.get());
	
	//Method reference writing
	su=i1::toString ;
	System.out.println(su.get());
}
Class name calls static

Class name::static state

public static void main(String[] args) {
	Function<String,Integer>function=Integer::parseInt;
	System.out.println(function.apply("123"));
	
	Function<String, Integer> fun = new Function<String,Integer>(){
		@Override
		public Integer apply(String t) {
			// TODO Auto-generated method stub
			return null;
		}
	};
	fun=x->Integer.parseInt(x);
	fun=Integer::parseInt;
	
	//The first two are input parameters and the third is return value
	BiFunction<Integer,Integer,Integer>bif=Integer::max;
	System.out.println(bif.apply(123,323));
	test((B x)->System.out.println(x));
	
}
public static void test(A a){
	
	}
}
interface A{
	public void m1(B b);
}
class B{
	
}
Class name calling member

public static void main(String[]args){
	BiPredicate<String,String>bp=String::equals;
	System.out.println(bp.test("abc","abc"));
}

2.8 construction method call

two point nine   Array reference

 4.Stream API

Concept description

Data channels and pipelines are used to operate the element sequences generated by data sources (sets, arrays, etc.).

                   

Collection is about data, and flow is about computation

                   

That is, a set of API s used to process arrays and collections.

4.2 features

Stream is not a data structure and has no internal storage. It will not store elements by itself.

                   

Stream does not change the source object. Instead, they return a new stream that holds the result.

                   

Stream operations are deferred. This means that they wait until the results are needed.

                   

Index access is not supported.

                   

Delay calculation

                   

Support parallelism

                   

It is easy to generate data or collections

                   

Support filtering, searching, conversion, summary, aggregation and other operations.

4.3 application scenarios

Stream computing requires delayed computing and more convenient parallel computing

                   

More flexible and concise collection processing scenarios

4.4 code implementation

4.4.1 description of operation mechanism

Stream is divided into source, intermediate operation and termination operation.

                   

The source of a stream can be an array, a collection, a generator method, an I/O channel, and so on.

                   

A stream can have zero or more intermediate operations. Each intermediate operation will return a new stream for the next operation. A stream will only have one termination operation.

          

Intermediate operations are also called transformation operators

                   

Only when a Stream encounters a termination operation, its data source will begin to perform a traversal operation.

                   

The termination operation is also called action operator action

Because the return value of the action operator is no longer stream, the calculation is terminated

Only when we encounter the action operator can we really calculate

4.4.2 method of creating flow

 

 

Posted by ma5ect on Tue, 02 Nov 2021 10:40:41 -0700