JAVA8 ten new features detailed _java

Source: Internet
Author: User
Tags time zones new set readable time and date uuid wrapper multiple inheritance in c google guava

"Java is still not dead-and people are starting to figure."

This tutorial will describe the new features with a simple annotated code, and you will not see a lot of scary text.

The default method of an interface

Java 8 allows us to add a Non-abstract method implementation to the interface, just using the default keyword, which is called an extension method, as follows:

Copy Code code as follows:

Interface Formula {
Double calculate (int a);

Default double sqrt (int a) {
Return Math.sqrt (a);
}
}




The formula interface defines the SQRT method in addition to the Calculate method, and implements a subclass of the formula interface to implement only one calculate method, and the default method sqrt will be used directly on the subclass.


Copy Code code as follows:

Formula Formula = new Formula () {
@Override
public double Calculate (int a) {
return sqrt (A * 100);
}
};

Formula.calculate (100); 100.0
FORMULA.SQRT (16); 4.0




The formula in this article is implemented as an instance of an anonymous class, which is very easy to understand and 6 lines of code implement the computed sqrt (A * 100). In the next section, we'll see a simpler way to implement a single method interface.

Translator Note: In Java, only single inheritance, if you want to give a class A new attribute, usually by using an interface, which supports multiple inheritance in C + +, allows a subclass to have both the interface and the functionality of multiple parent classes, and in other languages, the method of having a class with other reusable code is called Mixin. This special new Java 8 is closer to Scala's trait in terms of compiler implementations. It is also known in C # as the concept of extension methods, allowing for existing type extension methods, which are semantically different from that of Java 8.

Second, LAMBDA expression

First look at how strings are arranged in the old version of Java:

Copy Code code as follows:

list<string> names = Arrays.aslist ("Peter", "Anna", "Mike", "Xenia");

Collections.sort (names, new comparator<string> () {
@Override
public int Compare (string A, string b) {
Return B.compareto (a);
}
});




You only need to pass a list object to the static method Collections.sort and a comparer to arrange in the specified order. It is common practice to create an anonymous comparer object and pass it to the sort method.

In Java 8 You don't need to use this traditional way of anonymous objects, Java 8 provides a simpler syntax, lambda expression:

Copy Code code as follows:

Collections.sort (names, (string A, string b)-> {
Return B.compareto (a);
});



See, the code becomes more and more readable, but it can actually be written a little shorter:


Copy Code code as follows:

Collections.sort (names, (string A, string b)-> B.compareto (a));



For a function body with only one line of code, you can remove the curly braces {} and the return keyword, but you can write a little shorter:


Copy Code code as follows:

Collections.sort (names, (A, B)-> B.compareto (a));



The Java compiler can automatically deduce parameter types, so you can not write again. Let's look at what the lambda expression can do to make things easier:





Third, function-type interface



How is a lambda expression represented in a Java type system? Each lambda expression corresponds to a type, usually the interface type. A "functional interface" refers to an interface that contains only an abstract method, and each lambda expression of that type is matched to this abstract method. Because the default method is not an abstract method, you can also add a default method to your functional interface.

We can use lambda expressions as any type of interface that contains only one abstract method, and make sure that your interface does that, and you just add @FunctionalInterface annotations to your interface. The compiler will make an error if it finds that there are more than one abstract method for the interface in which you have annotated the annotation.

Examples are as follows:

Copy Code code as follows:

@FunctionalInterface
Interface Converter<f, t> {
T convert (F from);
}
converter<string, integer> Converter = (from)-> integer.valueof (from);
Integer converted = Converter.convert ("123");
System.out.println (converted); 123



Note that if @functionalinterface is not specified, the above code is also true.

The translator maps a lambda expression to a single method interface, which is implemented in a different language before Java 8, such as the Rhino JavaScript interpreter, if a function parameter receives a single method interface and you pass a Function,rhino The interpreter automatically makes a single interface instance to the function adapter, and the typical scenario has org.w3c.dom.events.EventTarget AddEventListener the second parameter eventlistener.

Iv. methods and constructor references

The code in the previous section can also be represented by a static method reference:

Copy Code code as follows:

converter<string, integer> Converter = integer::valueof;
Integer converted = Converter.convert ("123");
System.out.println (converted); 123



Java 8 allows you to use:: Keyword to pass a method or constructor reference, the above code shows how to refer to a static method, we can also refer to the method of an object:


Copy Code code as follows:

converter = Something::startswith;
String converted = Converter.convert ("Java");
System.out.println (converted); J



Next look at how the constructor uses:: Keyword to reference, first we define a simple class that contains multiple constructors:


Copy Code code as follows:

Class Person {
String FirstName;
String LastName;

Person () {}

Person (string firstName, String lastName) {
This.firstname = FirstName;
This.lastname = LastName;
}
}




Next we specify an object factory interface to create the person object:


Copy Code code as follows:

Interface Personfactory<p extends Person> {
P Create (String firstName, string lastName);
}



Here we use constructor references to correlate them, rather than implement a complete factory:


Copy Code code as follows:

personfactory<person> personfactory = person::new;
Person person = personfactory.create ("Peter", "Parker");



We only need to use person::new to get a reference to the person class constructor, and the Java compiler automatically chooses the appropriate constructor based on the signature of the Personfactory.create method.

V. LAMBDA scope

The way in which you access an outer scope and an older version of an anonymous object in a lambda expression is similar. You can directly access the outer local variables marked final, or the fields of the instance and the static variables.

Vi. Accessing local variables

We can access the outer local variables directly in the lambda expression:

Copy Code code as follows:

final int num = 1;
Converter<integer, string> stringconverter =
(from)-> string.valueof (from + num);

Stringconverter.convert (2); 3




But unlike an anonymous object, the variable num here can be no longer declared final, and the code is equally correct:


Copy Code code as follows:

int num = 1;
Converter<integer, string> stringconverter =
(from)-> string.valueof (from + num);

Stringconverter.convert (2); 3




However, NUM must not be modified by the following code (that is, the implicit final semantics), for example:


Copy Code code as follows:

int num = 1;
Converter<integer, string> stringconverter =
(from)-> string.valueof (from + num);
num = 3;



Attempting to modify num in a lambda expression is also not allowed.





Vii. accessing object fields and static variables

Unlike local variables, the fields within the lambda for instance and static variables are both readable and writable. This behavior is consistent with the anonymous object:

Copy Code code as follows:
Class Lambda4 {
static int outerstaticnum;
int outernum;

void Testscopes () {
Converter<integer, string> stringConverter1 = (from)-> {
Outernum = 23;
Return string.valueof (from);
};

Converter<integer, string> stringConverter2 = (from)-> {
Outerstaticnum = 72;
Return string.valueof (from);
};
}
}







The default method of accessing the interface



Remember the formula example in the first section, interface formula defines a default method sqrt can be accessed directly by an instance of formula, but this is not possible in lambda expressions.


The default method cannot be accessed in a lambda expression, the following code cannot be compiled:


Copy Code code as follows:

Formula Formula = (a)-> sqrt (A * 100);
Built-in functional interfaces



The JDK 1.8 API contains a number of built-in functional interfaces that are commonly used in old Java, such as comparator or runnable interfaces, that add @functionalinterface annotations to use on a lambda.


The Java 8 API also offers a number of new functional interfaces to make work more convenient, with some interfaces coming from the Google Guava Library, and even if you're familiar with them, it's important to see how these extend to the lambda.





Predicate Interface

The predicate interface has only one parameter, which returns a Boolean type. The interface contains a variety of default methods to synthesize predicate groups into other complex logic (e.g., with, or, non):

Copy Code code as follows:

predicate<string> predicate = (s)-> s.length () > 0;

Predicate.test ("foo"); True
Predicate.negate (). Test ("foo"); False

predicate<boolean> nonnull = objects::nonnull;
predicate<boolean> isNull = objects::isnull;

Predicate<string> isempty = String::isempty;
predicate<string> isnotempty = Isempty.negate ();







Function Interface

The function interface has a parameter and returns a result with some default methods that can be combined with other functions (compose, andthen):

Copy Code code as follows:

function<string, integer> tointeger = integer::valueof;
function<string, string> backtostring = Tointeger.andthen (string::valueof);

Backtostring.apply ("123"); "123"







Supplier Interface



The Supplier interface returns an arbitrary value, and unlike a function interface, the interface has no parameters


Copy Code code as follows:

supplier<person> personsupplier = person::new;
Personsupplier.get (); New person






Consumer Interface



The Consumer interface represents the execution of an operation on a single parameter.


Copy Code code as follows:

consumer<person> greeter = (p)-> System.out.println ("Hello," + p.firstname);
Greeter.accept (New person ("Luke", "Skywalker"));






Comparator Interface



Comparator is a classic interface in old Java, where Java 8 adds a variety of default methods:


Copy Code code as follows:

Comparator<person> Comparator = (P1, p2)-> p1.firstName.compareTo (p2.firstname);

person P1 = new Person ("John", "Doe");
person P2 = new Person ("Alice", "Wonderland");

Comparator.compare (P1, p2); > 0
Comparator.reversed (). Compare (P1, p2); < 0







Optional Interface

Optional is not a function is an interface, this is to prevent the nullpointerexception exception of the auxiliary type, this is the next session will be used in the important concept, now let's simply look at what this interface can do:

Optional is defined as a simple container whose value may be null or not NULL. Before Java 8, a function should normally return a Non-empty object but occasionally return null, whereas in Java 8 it is not recommended that you return NULL instead of returning to optional.

Copy Code code as follows:

optional<string> Optional = Optional.of ("Bam");

Optional.ispresent (); True
Optional.get (); "Bam"
Optional.orelse ("fallback"); "Bam"

Optional.ifpresent ((s)-> System.out.println (S.charat (0)); "B"







Stream Interface

Java.util.Stream represents the sequence of actions that can be applied to the last execution of a set of elements. The stream operation is divided into intermediate or final operations, and the final operation returns a specific type of calculation, while the intermediate operation returns the stream itself, so that you can string multiple operations sequentially. The creation of the Stream needs to specify a data source, such as a subclass of Java.util.Collection, a list, or set, which is not supported by the map. The operation of the stream can be executed serially or in parallel.

First look at how the stream is used, first create the data list used by the instance code:

Copy Code code as follows:

list<string> stringcollection = new arraylist<> ();
Stringcollection.add ("Ddd2");
Stringcollection.add ("Aaa2");
Stringcollection.add ("BBB1");
Stringcollection.add ("Aaa1");
Stringcollection.add ("Bbb3");
Stringcollection.add ("CCC");
Stringcollection.add ("Bbb2");
Stringcollection.add ("Ddd1");



Java 8 expands the collection class to create a stream by Collection.stream () or Collection.parallelstream (). The following sections explain the common stream operations in detail:

Filter filters

Filtering is filtered through a predicate interface and retains only the qualifying elements, which are intermediate operations, so we can filter the results to apply other stream operations (such as foreach). foreach requires a function to execute the filtered elements sequentially. foreach is a final operation, so we cannot perform other stream operations after foreach.

Copy Code code as follows:

StringCollection
. Stream ()
. Filter ((s)-> S.startswith ("a"))
. ForEach (System.out::p rintln);

"Aaa2", "Aaa1"







Sort Sorting

The sort is an intermediate operation that returns the sorted stream. If you do not specify a custom comparator, the default sort is used.

Copy Code code as follows:

StringCollection
. Stream ()
. Sorted ()
. Filter ((s)-> S.startswith ("a"))
. ForEach (System.out::p rintln);

"Aaa1", "Aaa2"




It should be noted that the sort only creates an arranged stream, without affecting the original data source, after which the original data stringcollection are not modified:


Copy Code code as follows:

System.out.println (StringCollection);
DDD2, Aaa2, BBB1, AAA1, Bbb3, CCC, BBB2, DDD1






map Map



The intermediate action map converts elements to another object in turn based on the specified function interface, and the following example shows the conversion of a string to an uppercase string. You can also convert objects to other types by map, and the stream type returned by the map is determined by the return value of the function you pass in the map.


Copy Code code as follows:

StringCollection
. Stream ()
. Map (String::touppercase)
. Sorted ((A, B)-> B.compareto (a))
. ForEach (System.out::p rintln);

"DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"







Match matches

Stream provides a variety of matching operations that allow you to detect whether the specified predicate matches the entire stream. All matching operations are final and return a Boolean value.

Copy Code code as follows:

Boolean Anystartswitha =
StringCollection
. Stream ()
. AnyMatch ((s)-> S.startswith ("a"));

System.out.println (Anystartswitha); True

Boolean Allstartswitha =
StringCollection
. Stream ()
. Allmatch ((s)-> S.startswith ("a"));

System.out.println (Allstartswitha); False

Boolean Nonestartswithz =
StringCollection
. Stream ()
. Nonematch ((s)-> s.startswith ("z"));

System.out.println (Nonestartswithz); True

Count Count

The count is a final operation that returns the number of elements in the stream and the return value type is long.

Copy Code code as follows:

Long STARTSWITHB =
StringCollection
. Stream ()
. Filter ((s)-> s.startswith ("B"))
. Count ();

System.out.println (STARTSWITHB); 3







Reduce Statute

This is a final operation that allows multiple elements of a stream to be defined as an element by a specified function, and the resulting result is represented by the optional interface:

Copy Code code as follows:

Optional<string> reduced =
StringCollection
. Stream ()
. Sorted ()
. reduce ((S1, S2)-> s1 + "#" + S2);

Reduced.ifpresent (System.out::p rintln);
"Aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"







Parallel Streams

As mentioned earlier, the stream has both serial and parallel, and the operation on the serial stream is completed sequentially in one thread, while the parallel stream is executed concurrently on multiple threads.

The following example shows how to improve performance by parallel stream:

First we create a large table with no repeating elements:

Copy Code code as follows:

int max = 1000000;
list<string> values = new arraylist<> (max);
for (int i = 0; i < max; i++) {
UUID uuid = Uuid.randomuuid ();
Values.add (Uuid.tostring ());
}



And then we calculate how long it takes to sort this stream,


Serial Sort:


Copy Code code as follows:

Long T0 = System.nanotime ();

Long Count = Values.stream (). Sorted (). Count ();
System.out.println (count);

Long T1 = System.nanotime ();

Long Millis = TimeUnit.NANOSECONDS.toMillis (t1-t0);
System.out.println (String.Format ("sequential sort took:%d ms", Millis));

Serial time consuming: 899 ms
Parallel sorting:

Copy Code code as follows:

Long T0 = System.nanotime ();

Long Count = Values.parallelstream (). Sorted (). Count ();
System.out.println (count);

Long T1 = System.nanotime ();

Long Millis = TimeUnit.NANOSECONDS.toMillis (t1-t0);
System.out.println (String.Format ("parallel sort took:%d ms", Millis));

Parallel sorting time consuming: 472 ms
The above two code is almost the same, but the parallel version of the 50% faster, the only change is to change the stream () to Parallelstream ().

Map

As mentioned earlier, the map type does not support stream, but map provides some new and useful ways to handle some of the day-to-day tasks.

Copy Code code as follows:

Map<integer, string> map = new hashmap<> ();

for (int i = 0; i < i++) {
Map.putifabsent (i, "Val" + i);
}

Map.foreach ((ID, Val)-> System.out.println (Val));
The code above is easy to understand, Putifabsent does not require additional presence checks, and foreach receives a consumer interface to manipulate each key-value pair in the map.

The following example shows the other useful functions on the map:

Copy Code code as follows:

Map.computeifpresent (3, (Num, Val)-> val + num);
Map.get (3); Val33

Map.computeifpresent (9, (Num, val)-> null);
Map.containskey (9); False

Map.computeifabsent (num-> "val" + num);
Map.containskey (23); True

Map.computeifabsent (3, num-> "Bam");
Map.get (3); Val33




Next shows how to delete an item in the map that matches all of the key values:


Copy Code code as follows:

Map.Remove (3, "Val3");
Map.get (3); Val33

Map.Remove (3, "val33");
Map.get (3); Null




Another useful method:


Copy Code code as follows:

Map.getordefault ("not Found"); Not found



Merging the elements of a map also becomes easy:


Copy Code code as follows:

Map.merge (9, "VAL9", (value, NewValue)-> Value.concat (newvalue));
Map.get (9); Val9

Map.merge (9, "concat", (value, NewValue)-> Value.concat (newvalue));
Map.get (9); Val9concat




What the merge does is insert if the key name does not exist, otherwise the value corresponding to the original key is merged and reinserted into the map.

Nine, Date API

The Java 8 contains a new set of time and date APIs under the package Java.time. The new date API is similar to the open source Joda-time library, but not exactly the same, and the following example shows the most important parts of this new set of APIs:

Clock Clock

The clock class provides a way to access the current date and time, clock is time zone sensitive and can be used instead of system.currenttimemillis () to get the current number of microseconds. A particular point in time can also be represented using the instant class, which can also be used to create old Java.util.Date objects.

Copy Code code as follows:

Clock Clock = Clock.systemdefaultzone ();
Long Millis = Clock.millis ();

Instant Instant = Clock.instant ();
Date legacydate = Date.from (instant); Legacy Java.util.Date







timezones time Zone

In the new API, the time zone is represented using ZoneID. Time zones can be easily obtained by using the static method of. Time zones define the time difference to UTS times and are extremely important when converting between instant Point-in-time objects to local date objects.

Copy Code code as follows:

System.out.println (Zoneid.getavailablezoneids ());
Prints all available timezone IDs

ZoneID zone1 = Zoneid.of ("Europe/berlin");
ZoneID zone2 = Zoneid.of ("Brazil/east");
System.out.println (Zone1.getrules ());
System.out.println (Zone2.getrules ());

ZONERULES[CURRENTSTANDARDOFFSET=+01:00]
ZONERULES[CURRENTSTANDARDOFFSET=-03:00]







localtime local time

LocalTime defines a time with no time zone information, such as 10 o'clock in the evening, or 17:30:15. The following example creates two local times using the time zone created by the preceding code. Then compares the time and calculates the time difference of two times in hours and minutes:

Copy Code code as follows:

LocalTime Now1 = Localtime.now (Zone1);
LocalTime now2 = Localtime.now (zone2);

System.out.println (Now1.isbefore (now2)); False

Long Hoursbetween = ChronoUnit.HOURS.between (Now1, Now2);
Long Minutesbetween = ChronoUnit.MINUTES.between (Now1, Now2);

System.out.println (Hoursbetween); -3
System.out.println (Minutesbetween); -239




LocalTime provides a variety of factory methods to simplify the creation of objects, including parsing time strings.


Copy Code code as follows:

LocalTime late = Localtime.of (23, 59, 59);
System.out.println (late); 23:59:59

DateTimeFormatter Germanformatter =
DateTimeFormatter
. Oflocalizedtime (Formatstyle.short)
. Withlocale (Locale.german);

LocalTime leettime = Localtime.parse ("13:37", Germanformatter);
System.out.println (Leettime); 13:37


Localdate Local Date

Localdate indicated an exact date, such as 2014-03-11. The value of the object is immutable and is basically consistent with localtime. The following example shows how to add a day/month/year to a Date object. Also note that these objects are immutable and that the operation returns a new instance.

Copy Code code as follows:

Localdate today = Localdate.now ();
Localdate tomorrow = Today.plus (1, chronounit.days);
Localdate yesterday = tomorrow.minusdays (2);

Localdate IndependenceDay = Localdate.of (2014, month.july, 4);
DayOfWeek DayOfWeek = Independenceday.getdayofweek ();




System.out.println (DayOfWeek); FRIDAY


Parsing a localdate type from a string is as simple as parsing localtime:


Copy Code code as follows:

DateTimeFormatter Germanformatter =
DateTimeFormatter
. Oflocalizeddate (Formatstyle.medium)
. Withlocale (Locale.german);

Localdate Xmas = localdate.parse ("24.12.2014", Germanformatter);
System.out.println (xmas); 2014-12-24







LocalDateTime Local Date Time

LocalDateTime also represents the time and date, which is equivalent to merging the first two sections onto an object. LocalDateTime and LocalTime, as well as localdate, are immutable. LocalDateTime provides a number of ways to access specific fields.

Copy Code code as follows:

LocalDateTime Sylvester = Localdatetime.of (2014, Month.december, 31, 23, 59, 59);

DayOfWeek DayOfWeek = Sylvester.getdayofweek ();
System.out.println (DayOfWeek); Wednesday

Month Month = Sylvester.getmonth ();
SYSTEM.OUT.PRINTLN (month); December

Long Minuteofday = Sylvester.getlong (Chronofield.minute_of_day);
System.out.println (Minuteofday); 1439




As long as the time zone information is appended, it can be converted to a Point-in-time instant object, and the instant object can easily be converted to an old-fashioned java.util.Date.


Copy Code code as follows:

Instant Instant = Sylvester
. Atzone (Zoneid.systemdefault ())
. Toinstant ();

Date legacydate = Date.from (instant);
System.out.println (legacydate); Wed Dec 23:59:59 CET 2014




Formatting localdatetime and formatting times and dates, in addition to using predefined formats, we can define the format ourselves:


Copy Code code as follows:

DateTimeFormatter formatter =
DateTimeFormatter
. Ofpattern ("MMM DD, yyyy-hh:mm");

LocalDateTime parsed = Localdatetime.parse ("Nov, 2014-07:13", formatter);
String string = Formatter.format (parsed);
System.out.println (string); Nov 03, 2014-07:13




Unlike Java.text.NumberFormat, the new version of the DateTimeFormatter is immutable, so it is thread-safe.


More information about time date format: http://download.java.net/jdk8/docs/api/java/time/format/DateTimeFormatter.html

Ten, Annotation annotation

To support multiple annotations in Java 8, let's look at an example to understand what it means.
First, define a wrapper class hints annotation used to place a specific set of hint annotations:

Copy Code code as follows:

@interface Hints {
Hint[] Value ();
}

@Repeatable (Hints.class)
@interface Hint {
String value ();
}




Java 8 allows you to use annotations of the same type multiple times, just to annotate the annotation with @repeatable.

Example 1: Use the wrapper class as a container to save multiple annotations (old method)

Copy Code code as follows:

@Hints ({@Hint ("Hint1"), @Hint ("Hint2")})
Class Person {}



Example 2: Using multiple annotations (new method)


Copy Code code as follows:

@Hint ("Hint1")
@Hint ("Hint2")
Class Person {}



In the second example, the Java compiler implicitly helps you define @hints annotations, and knowing this can help you get this information using reflection:


Copy Code code as follows:

Hint Hint = Person.class.getAnnotation (Hint.class);
SYSTEM.OUT.PRINTLN (hint); Null

Hints hints1 = Person.class.getAnnotation (Hints.class);
System.out.println (Hints1.value (). length); 2

hint[] hints2 = Person.class.getAnnotationsByType (Hint.class);
System.out.println (hints2.length); 2




Even if we do not define @hints annotations on the person class, we can get @Hints annotations through Getannotation (Hints.class), and it is more convenient to use the Getannotationsbytype You can get all the @hint annotations directly.


In addition, the annotations to Java 8 are added to two new target types:


Copy Code code as follows:

@Target ({elementtype.type_parameter, elementtype.type_use})
@interface Myannotation {}



As for the new features of Java 8, there are certainly more features waiting to be discovered. JDK 1.8 also has a lot of useful things, such as Arrays.parallelsort, Stampedlock and Completablefuture, and so on.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.