Java 8 has been released for some time. This release has changed a lot. Many people compare this change with the upgrade of Java 5. One of the important new features of Java 8 is lambda expressions, which allow us to pass behavior into functions. Think about it. Before Java 8, we wanted to pass behavior into functions. The only choice was anonymous inner classes. After the release of Java 8, lambda expressions will largely replace the use of anonymous inner classes, simplifying the code while highlighting the most important part of the original anonymous inner classes that contains real logic. Especially for students who do data, when they are used to using functional programming languages like scala, they will have a deeper understanding. Now let's look at some common expressions for lambda in Java 8.
The parameter list and return value type of the method invoked in the lambda body should be consistent with the parameter list and return value type of the abstract method in the functional interface.
I. Replacing anonymous inner classes
lambda expressions are mostly used to replace anonymous inner classes. Implementing Runnable interfaces is a classic example of anonymous inner classes. lambda expressions are powerful enough to replace the entire anonymous inner class with () - >!
package OSChina.Lambda; import org.junit.Test; import java.util.Comparator; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; public class Test1{ public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Ordinary, thread startup"); } }; runnable.run(); test2(); test3(); test4(); test5(); } //No parameter, no return value public static void test2() { //There is only one parenthesis on the left to indicate that there are no parameters, and on the right is the Lambda body (which implements the method in the anonymous inner class), (that is, a usable interface implementation class). ) Runnable runnable = ()->System.out.println("Lambda Expressions, thread startup"); runnable.run(); } //There is one parameter and no return value. public static void test3() { //This e represents the parameters of the method of the implemented interface. Consumer<String> consumer = e->System.out.println("Lambda Expressions,"+e); consumer.accept("Afferent parameters"); } //There are more than two parameters, a return value, and multiple statements in the Lambda body public static void test4() { //There are many statements in Lambda body, remember to bracket them Comparator<Integer> com = (x, y) -> { System.out.println("Functional interface"); return Integer.compare(x, y); }; int compare = com.compare(100, 244); System.out.println("There are more than two parameters with a return value,"+compare); } //If there is only one statement in the Lambda body, return and braces can be omitted. public static void test5() { //Comparator com = (x, y) -> Integer.compare(100, 244); System.out.println("if Lambda There is only one statement in the body. return Both braces and braces can be omitted.,"+Integer.compare(100, 244)); } }
Four Built-in Functional Interfaces in Java 8
It's too cumbersome to write an interface on your own using lambda, so Java provides some interfaces on its own:
1. Consumer consumer interface: void accept (T);
//There is one parameter and no return value. public static void test3() { //This e represents the parameters of the method of the implemented interface. Consumer<String> consumer = e->System.out.println("Lambda Expressions,"+e); consumer.accept("Afferent parameters"); }
2. Supplier supply interface: T get();
package OSChina.Lambda; import java.util.ArrayList; import java.util.function.Supplier; public class Test2 { public static void main(String[] args) { ArrayList<Integer> res = getNumList(10,()->(int)(Math.random()*100)); System.out.println(res); } public static ArrayList<Integer> getNumList(int num, Supplier<Integer> sup){ ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { Integer e = sup.get(); list.add(e); } return list; } }
3. Function functional interface: R apply (T);
package OSChina.Lambda; import java.util.function.Function; public class Test2 { public static void main(String[] args) { String newStr = strHandler("abc",(str)->str.toUpperCase()); System.out.println(newStr); newStr = strHandler(" abc ",(str)->str.trim()); System.out.println(newStr); } public static String strHandler(String str, Function<String,String>fun){ return fun.apply(str); } }
4. Predicate assertive interface: Boolean test (T);
Judge some string arrays Judge strings with length > 2:
package OSChina.Lambda; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class Test2 { public static void main(String[] args) { List<String> list = Arrays.asList("hello","jiangshuying","lambda","www","ok","q"); List<String> ret = filterStr(list,(str)->str.length()>2); System.out.println(ret); } public static List<String> filterStr(List<String> list, Predicate<String> pre){ ArrayList<String> arrayList = new ArrayList<>(); for(String str:list){ if(pre.test(str)) { arrayList.add(str); } } return arrayList; } }
Method Reference and Constructor Reference
Requirements: To realize the parameter list and return value type of abstract method, the parameter list and return value type of method reference must be consistent!
Method Reference: Use the operator ":" to separate classes from methods.
Object: Instance method name
Class: Static method name
Class: Instance method name
For instance:
public static void test9(){ Comparator<Integer> comparator = (x,y)->Integer.compare(x,y); Comparator<Integer> comparator1 = Integer::compare; int compare = comparator.compare(1,2); int compare1 = comparator1.compare(1,2); System.out.println("compare:"+compare); System.out.println("compare1:"+compare1); }
4. Some Common Usages of lambda Expressions
1. Iteration of sets using lambda expressions
package OSChina.Lambda; import java.util.Arrays; import java.util.List; public class Test3 { public static void main(String[] args) { List<String> list = Arrays.asList("java","c#","javascript"); //before java8 for (String str:list){ System.out.println("before java8,"+str); } //after java8 list.forEach(x-> System.out.println("after java8,"+x)); } }
2. Implementing map with lambda expression
Map function can be said to be the most important method in functional programming. The function of map is to transform one object into another. In our example, the cost is increased by 0,05 times by map method and then output.
package OSChina.Lambda; import java.util.Arrays; import java.util.List; public class Test3 { public static void main(String[] args) { List<Double> list = Arrays.asList(10.0,20.0,30.0); list.stream().map(x->x+x*0.05).forEach(x-> System.out.println(x)); } }
3. Implementing map and reduce with lambda expression
Now that you mention map, how can you not mention reduce? Reduction, like map, is one of the most important methods in functional programming. The function of map is to change one object into another, while reduce implements merging all values into one. See:
package OSChina.Lambda; import java.util.Arrays; import java.util.List; public class Test3 { public static void main(String[] args) { //before java8 List<Double> cost = Arrays.asList(10.0, 20.0,30.0); double sum = 0; for(double each:cost) { each += each * 0.05; sum += each; } System.out.println("before java8,"+sum); //after java8 List<Double> list = Arrays.asList(10.0,20.0,30.0); double sum2 = list.stream().map(x->x+x*0.05).reduce((sum1,x)->sum1+x).get(); System.out.println("after java8,"+sum2); } }
It is believed that the map+reduce+lambda expression is written more than one level higher.
4. filter operation
Filter is also an operation we often use. When manipulating collections, it is often necessary to filter out some elements from the original collection.
package OSChina.Lambda; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Test3 { public static void main(String[] args) { List<Double> cost = Arrays.asList(10.0, 20.0,30.0,40.0); List<Double> filteredCost = cost.stream().filter(x -> x > 25.0).collect(Collectors.toList()); filteredCost.forEach(x -> System.out.println(x)); } }
5. Cooperate with Predicate of Functional Interface
In addition to supporting functional programming style at the language level, Java 8 also adds a package called java.util.function. It contains many classes to support functional programming in Java. One is Predicate, which uses java.util.function.Predicate functional interfaces and lambda expressions to add logic to API methods and support more dynamic behavior with less code. The Predicate interface is well suited for filtering.
package OSChina.Lambda; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class Test4 { public static void filterTest(List<String> languages, Predicate<String> condition) { languages.stream().filter(x -> condition.test(x)).forEach(x -> System.out.println(x + " ")); } public static void main(String[] args) { List<String> languages = Arrays.asList("Java","Python","scala","Shell","R"); filterTest(languages,x->x.startsWith("J"));//Java filterTest(languages,x -> x.endsWith("a"));//Java,scala filterTest(languages,x -> true);//Java,Python,scala,Shell,R filterTest(languages,x -> false);// filterTest(languages,x -> x.length() > 4);//Python,scala,Shell, } }