List of articles
-
-
- Functional programming
- JDK8 New interface features
- The function interface
- Method reference
-
Functional programming
Functional programming is more often a way of thinking in programming , It’s a methodology . The difference between functional programming and imperative programming is that : Functional programming is telling the code what you’re going to do , Imperative programming tells the code how to do it . In short , Functional programming is based on some syntax or call API To program .
for example , Find the smallest number in the integer array , Using command programming to achieve the following :
public static void main(String[] args){
int[] array={
1,2,3,4,5,6,7,8,9,10};
int minx=Integer.MAX_VALUE;
for(int a:array){
if(a<minx)
minx=a;
}
System.out.println(minx);
}
And using functional programming to achieve , It is simplified to the following code :
int[] array = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int minx = IntStream.of(array).min().getAsInt();
System.out.println(minx);
We can see that , Imperative programming needs to implement its own specific logic , Functional programming, on the other hand, calls API It needs to be done , Write imperative code as a series of function calls , In functional programming, the code is more concise 、 Understandability , That’s one of the reasons for functional programming . So functional programming is about telling code what you’re going to do , Imperative programming tells the code how to do it , It’s a shift in thinking .
and lambda
Expressions are the basis of functional programming , It’s very important :
stay Java
I won’t support it lambda
In terms of expression , We’re going to create a thread like this :
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run() Method ");
}
}).start();
And use lambda
expression :
new Thread(() -> System.out.println("run()")).start();
lambda
In a word, the expression completes the creation of the thread , It emphasizes the input and output of the function , And hide the internal implementation details , And it can receive functions as input ( Parameters ) And the output ( Return value ).
stay ->
On the left is input , On the right is the output . The above code parameter is empty .
The lambda
The function of an expression is to return Runnable
Interface implementation object , This calls a method to get the instance object, similar to , Just write the implementation code directly into the lambda
Expression .
JDK8 New interface features
-
The function interface , An interface can only have one method that needs to be implemented , have access to
FunctionalInterface
Make a statement with comments@FunctionalInterface public interface InterfaceOne { int doubleNum(int i); }
Use
lambda
Expression to obtain the implementation of the interface instance of several writing :InterfaceOne num1 = (i) -> i * 2; System.out.println(num1.doubleNum(10)); InterfaceOne num2 = i -> i * 2; // Specify parameter type InterfaceOne num3 = (int i) -> i * 2; InterfaceOne num4 = (int i) -> { System.out.println(i); return i * 2; };
-
Default method for interface , Used to provide a default implementation . The default method is the same as that of a normal implementation class , have access to
this
keyword .@FunctionalInterface public interface InterfaceOne { int doubleNum(int i); } default int add(int x,int y){ return x+y; }
The reason why the default method feature is more important , It’s because we can use this feature to provide default implementations on some of the previously written interfaces , And it doesn’t affect any implementation classes or existing code . For example, we are most familiar with List Interface , stay JDK1.2 since List The interface has not changed any code , here we are 1.8 After using this new feature, we added some default implementations . This is because if there is no feature of the default method , The impact of modifying the interface code is huge , And with the default method , Adding a default implementation does not affect any code .
-
When the interface has multiple inheritance , The problem of default method override may occur , In this case, the default method implementation of which interface should be specified .
@FunctionalInterface public interface InterfaceOne { int doubleNum(int i); default int add(int x, int y) { return x + y; } } @FunctionalInterface interface InterfaceTwo { int doubleNum(int i); default int add(int x, int y) { return x + y; } } @FunctionalInterface interface InterfaceThree extends InterfaceOne, InterfaceTwo { // Specifies the default method implementation of which interface to use @Override default int add(int x, int y) { return InterfaceOne.super.add(x, y); } }
The function interface
Interface Input parameters Return type explain Predicate T boolean Assertion Consumer T / Consume a data Function<T,R> T R Input T, Output R Supplier / T Provide a data UnaryOperator T T One variable function ( The input and output types are the same ) BiFunction<T,U,R> (T,U) R A function with two input parameters BinaryOperator (T,T) T Dual function ( The input and output types are the same ) The most common one is
Function
Interface , This interface saves us some unnecessary function interfaces . Use the following example to illustrateFunction
Interface :public class TestFunction { public static void main(String[] args) { Account account = new Account("FEEL", 9999999); Function<Long, String> func = i -> new DecimalFormat("#,###").format(i); account.show(func); } } class Account { private String name; private long balance; public Account(String name, long balance) { this.name = name; this.balance = balance; } public void show(Function<Long, String> func) { System.out.println(name + " The account balance of : " + func.apply(this.balance)); } }
Output is :
FEEL The account balance of : 9,999,999
If not used Function
Interface , You need to define your own interface , And chain operations are not supported .
@FunctionalInterface
interface Format {
String format(long i);
}
class Account {
private String name;
private long balance;
public Account(String name, long balance) {
this.name = name;
this.balance = balance;
}
public void show(Format fm) {
System.out.println(name + " The account balance of : " + fm.format(balance));
}
}
public class Test_No_Function {
public static void main(String[] args) {
Account account = new Account("FEEL", 999999999);
Format fm = i -> new DecimalFormat("#,###").format(i);
account.show(fm);
}
}
Here is Predicate
and Consumer
Use of interfaces :
public static void main(String[] args) {
// Assertion function interface
Predicate<Integer> p = i -> i > 0;
System.out.println("1>0? " + p.test(1));
// Consumer function interface
Consumer<String> consumer = System.out::println;
System.out.println("Hello Consumer Interface!");
}
Output results :
1>0? true
Hello Consumer Interface!
These interfaces generally encapsulate the basic types , So you don’t need to specify generics when using base types :
public static void main(String[] args){
// Assertion function interface
IntPredicate IP=i->i>0;
System.out.println(IP.test(1));
// Consumer function interface
IntConsumer ic=(v)->System.out.println(" Input integer :"+v);
ic.accept(1999);
}
Output results :
true
Input integer :1999
Here’s how to use some other interfaces :
public static void main(String[] args) {
// Provide data interface
Supplier<Integer> supplier = () -> 10;
System.out.println(" The data provided is : " + supplier.get());
// Univariate function interface
UnaryOperator<Integer> unaryOperator = i -> i >> 1;
System.out.println(" The result of the calculation is : " + unaryOperator.apply(10));
// Binary function interface
BinaryOperator<Integer> binaryOperator = (a, b) -> a * b;
System.out.println(" The result of the calculation is : " + binaryOperator.apply(10, 10));
}
The output is :
The data provided is : 10
The result of the calculation is : 5
The result of the calculation is : 100
Method reference
We usually use them lambda
Expression to create anonymous methods, but sometimes you just need to call an existing method . as follows :
Arrays.sort(array,(s1,s2)->s1.compareToIgnoreCase(s2));
And in the Jdk8
in , This can be simplified with a new feature lambda
expression :
Arrays.sort(array,String::compareToIgnoreCase);
This line is called Method Reference
( Method reference ), Its standard form is :
Class name :: Method name ::
( Just write the method name , There’s no need to write brackets )
Four forms of method references :
type | Example | Code example | Corresponding lambda expression |
---|---|---|---|
Reference static methods | ContainingClass::staticMethodName | String::valueOf | (s)->String.valueOf(s) |
An instance method that refers to an object | containingObject::instanceMethodName | x::toString() | ()->this.toString() |
An instance method that refers to any object of a certain type | ContainingType::methodName | String::toString | (s)->s.toString |
Reference construction method | ClassName::new | String::new | ()->new String() |
Define the entity class as follows :
package com.demo.after;
/**
* @author bushizhe
* @Time 2019 year 5 month 21 Japan Afternoon 4:38:56
* @Description
*/
public class FEEL {
private String name = "FEEL";
private int age = 21;
public FEEL() {
}
public FEEL(String name) {
this.name = name;
}
public FEEL(String name, int age) {
this.name = name;
this.age = age;
}
public static void show(FEEL feel) {
System.err.println(feel.name + " This year, " + feel.age + " Year old !!");
}
public int getAge(int age) {
System.out.println(name + " Age :" + age);
return age + 10;
}
@Override
public String toString() {
return "FEEL [name=" + name + ", age=" + age + "]";
}
}
Call method in entity class through method reference :
package com.demo.after;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.IntUnaryOperator;
import java.util.function.Supplier;
/**
* @author bushizhe
* @Time 2019 year 5 month 21 Japan Afternoon 4:44:20
* @Description
*/
public class TestMethod {
public static void main(String[] args) {
// Method reference , Call print method
Consumer<String> consumer = System.out::println;
consumer.accept(" Data received :");
// Static method reference
Consumer<FEEL> consumer2 = FEEL::show;
consumer2.accept(new FEEL("FEEL", 20));
// Instance method reference , Reference through an object instance
FEEL feel = new FEEL();
IntUnaryOperator func = feel::getAge;
System.out.println(" Ten years later :" + func.applyAsInt(20) + " year ");
// A reference to a nonparametric constructor ,
Supplier<FEEL> supplier = FEEL::new;
System.out.println(" Created a new object " + supplier.get());
// Method references with parameter constructors
BiFunction<String, Integer, FEEL> func2 = FEEL::new;
System.out.println(" Created a new object " + func2.apply("FLING", 20));
}
}
Output results :
Data received :
FEEL This year, 20 Year old !!
FEEL Age :20
Ten years later :30 year
Created a new object FEEL [name=FEEL, age=21]
Created a new object FEEL [name=FLING, age=20]