Original source: One ice _ Tian Jin
This article mainly records their own learning Java8 process, convenient for everyone to explore together and their own memo. Because I am also just beginning to learn Java8, so the text must have errors and understand the deviation of the place, I hope you help point out that I will continue to modify and optimize. This article is the first in this series, mainly introduces Java8 to the cock silk yard most attractive characteristic-lambda expression.
installation of Java8
Work desire good its its prerequisite, first install JDK8. The process is omitted, everyone should be able to do their own. But here's one thing to emphasize (Windows system): Currently we are working on a version of Java 6 or Java 7, so many people install JAVA8 Basic is learning. This way, there will be multiple versions of the JDK on your machine. And it is generally desirable to execute Java commands on the command line based on the old version of the JDK. However, if you enter: java-version on the command line after installing JDK8 and no path is set, JDK 8 is displayed on the screen. This is because when JDK8 is installed, the Java.exe is added by default in C:/windows/system32, which has a higher priority than the path setting. So even if the path is specified as an older version of the JDK, the Execute Java command will still show the new version of the JDK. All we have to do here is delete the Java.exe file in the C:/windows/system32 (Don't shake!) )。
Lambda First Experience
The following goes into the topic –LAMBDA expression. First, let's look at what a lambda expression is. Here is the explanation for "LAMBDA expression" on Wikipedia:
A function (or a subroutine) defined, and possibly called, without being bound to an identifier.
Simply put: a function that is not bound to an identifier and may be called. This explanation is not popular enough, as lambda expressions can be defined (imprecise, self-explanatory): a block of executable statements with input parameters. That's a good understanding, isn't it? A case wins thousands of words. Reader feedback: Don't understand the meaning of stream, so here's an example of a lambda expression that doesn't have a stream.
123 |
//这里省略list的构造 List<String> names = ...; Collections.sort(names, (o1, o2) -> o1.compareTo(o2)); |
12345678 |
//here omits the construction of List list<string> names = ...; collections.sort (names, new comparator<string> () { &NBSP;&NBSP; @Override &NBSP;&NBSP; Public int compare (string O1, String O2) { Code class= "Java Spaces" >&NBSP;&NBSP;&NBSP;&NBSP; return o1.compareto (O2); &NBSP;&NBSP; } }); |
The above two pieces of code are: use lambda expressions to sort and sort by using anonymous inner classes. This example can clearly see the effect of a lambda expression simplifying the code. Next, we show the mates of the lambda expression and its good base friend stream.
1234 |
List<String> names = new ArrayList<>(); names.add( "TaoBao" ); names.add( "ZhiFuBao" ); List<String> lowercaseNames = names.stream().map((String name) -> { return name.toLowerCase();}).collect(Collectors.toList()); |
This code is a list of strings, and each string contained therein is converted to a lowercase string (the classmates who are familiar with groovy and Scala will certainly feel very gracious). Note the Map method call in line Fourth of the code, where the map method accepts a lambda expression (actually a java.util.function.Function instance, which is described later).
Why do I need lambda expressions? Before trying to answer this question, let's take a look at what to do if we want to do the above code before Java8.
First look at the code of the ordinary Youth:
1234567 |
List<String> names = new ArrayList<>(); names.add( "TaoBao" ); names.add( "ZhiFuBao" ); List<String> lowercaseNames = new ArrayList<>(); for (String name : names) { lowercaseNames.add(name.toLowerCase()); } |
Next look at the code of the Literary Youth (with guava):
123456789 |
List<String> names =
new ArrayList<>();
names.add(
"TaoBao"
);
names.add(
"ZhiFuBao"
);
List<String> lowercaseNames = FluentIterable.from(names).transform(
new Function<String, String>() {
@Override
public String apply(String name) {
return name.toLowerCase();
}
}).toList();
|
Here, we no longer discuss the code style of ordinary youth and literary youth (the interested can go to Google search "imperative programming vs declarative Programming"). I prefer the declarative style of programming, so I prefer the writing of literary youth. But at the beginning of the literary Youth Code seems to be interfering with a little bit of information, the construction syntax of the anonymous class is slightly verbose. So Java8 lambda expression gives us a simpler syntax for creating a SAM (Single Abstract Method) interface.
Lambda Syntax explanation
Here we abstract the general syntax of lambda expressions:
123456 |
(Type1 param1, Type2 param2, ..., TypeN paramN) -> { statment1; statment2; //............. return statmentM; } |
As can be seen from the general syntax of the lambda expression, it is quite consistent with the definition of the imprecise version given above – "A block of executable statements with input parameters".
The lambda expression syntax above can be thought of as the most complete version, which is slightly cumbersome to write. Don't worry, here are a few simple versions of lambda expressions:
1. Parameter type omitted – in most cases, the compiler can infer the parameter type of a lambda expression from the context. So the lambda expression becomes:
123456 |
(param1,param2, ..., paramN) -> { statment1; statment2; //............. return statmentM; } |
So our first example becomes (omitting the creation of the list):
1 |
List<String> lowercaseNames = names.stream().map((name) -> { return name.toLowerCase();}).collect(Collectors.toList()); |
2. When the lambda expression has only one parameter number, you can omit the parentheses. The lambda expression is abbreviated as:
123456 |
param1 -> { statment1; statment2; //............. return statmentM; } |
So the first example is once again simplified to:
1 |
List<String> lowercaseNames = names.stream().map(name -> { return name.toLowerCase();}).collect(Collectors.toList()); |
3. When a lambda expression contains only one statement, you can omit the curly braces, return, and the semicolon at the end of the statement. The lambda expression is simplified to:
So the first example is once again simplified to:
1 |
List<String> lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList()); |
4. Using method Reference (described later in the syntax)
12 |
//注意,这段代码在Idea 13.0.2中显示有错误,但是可以正常运行 List<String> lowercaseNames = names.stream().map(String::toLowerCase).collect(Collectors.toList()); |
the outer world in the eyes of lambda expressions
As we've all described before, the lambda expression feels like a closed-out guy that can access the arguments passed to it, and can define the variables internally. But never see a variable that accesses it outside. Is the lambda expression not able to access its external variables? We can think of it this way: lambda expressions are actually quick to create the SAM interface Syntax sugar, the original Sam interface can access the interface external variables, lambda expression must also be able to (not only, in Java8 also made a small upgrade, described later).
1234 |
string[] array = { "a" "B" "C" }; for 1 2 3 &NBSP;&NBSP; stream.of (array). Map (item, Strings.padend (item, I, |
In this example above, the lambda expression in map accesses the external variable, integer i. and the ability to access external variables is an important feature of lambda expressions, so we can see the three important components of a lambda expression:
- Input parameters
- Executable statements
- Space to store external variables
However, a lambda expression accesses an external variable with a very important restriction: The variable is immutable (only the reference is immutable, not the true immutable).
1234 |
string[] array = { "a" "B" "C" }; for ( int i = 1 4 ; i++) { &NBSP;&NBSP; stream.of (array). Map (Item- > Strings.padend (item, I, ' @ ' |
The above code will report a compilation error. Because the variable i is referenced by a lambda expression, the compiler implicitly treats it as final (PS: You can imagine asking what the previous example does not give an error, and this error. The attentive reader will surely find it wrong. Before the anonymous inner class of Java accesses external variables, the external variables must be final decorated. Bingo, the JAVA8 has been optimized for this limitation (the small optimizations mentioned earlier), which can be used without a final decoration, but the compiler implicitly treats it as final.
the This in the Lambda eye
In Lambda, this is not the Sam object that the lambda expression produces, but the outer object that declares it.
method Reference and constructor reference (construct reference)
Method Reference
Before we introduce the lambda expression simplification, I have seen the figure of the method reference. A method reference can simplify the declaration of a lambda expression even more if certain conditions are true. The method reference syntax format has the following three types:
- Objectname::instancemethod
- Classname::staticmethod
- Classname::instancemethod
The first two approaches are similar, equivalent to invoking the parameters of the lambda expression directly as Instancemethod|staticmethod parameters. For example System.out::p rintln is equivalent to X->SYSTEM.OUT.PRINTLN (x), Math::max is equivalent to (x, y)->math.max (y).
The last method is equivalent to treating the first parameter of the lambda expression as the target object of the Instancemethod, and the remaining parameters as the parameters of the method. For example, String::tolowercase is equivalent to X->x.tolowercase ().
Constructor Reference
The constructor reference syntax is as follows: Classname::new, the parameters of the lambda expression are treated as parameters of the ClassName constructor. For example, Bigdecimal::new is equivalent to x->new BigDecimal (x).
Spit The Groove. Method Reference
On the surface, method references and constructor references further simplify the writing of lambda expressions, but personally feel that there is no more general use of Scala's underline syntax. Comparison can be seen, Cui Hua, on the code!
1234 |
List<String> names = new ArrayList<>(); names.add( "TaoBao" ); names.add( "ZhiFuBao" ); names.stream().map(name -> name.charAt( 0 )).collect(Collectors.toList()); |
The code above is given a string-type list, gets the first letter of each string, and synthesizes its group into a new list. There is no way to use the method reference to simplify this piece of code. Next, let's simply compare Scala's underline syntax (don't bother with Scala's syntax, this is just a comparison):
123 |
//省略List的初始化 List[String] names = .... names.map(_.charAt( 0 )) |
In Scala, you don't have to write a parameter declaration for a lambda expression.
referencing a document
- "Java SE 8 for the really impatient"
- Java 8 Tutorial
- Java 8 API Doc
JAVA8 First Experience (1): lambda expression syntax