summary
java8 has brought us many new features in the java language:
Faster speed, less code (new syntax Lambda expression is added), powerful Stream API, easy parallelism, minimizing null pointer exceptions, Optional, etc
Faster
Java8 updates the underlying data structure, the core of which is HashMap. In java7, the underlying data structure of HashMap is array plus single Necklace table, while java8 adopts array plus linked list plus red black tree.
Modified the garbage collection mechanism!
Less code
Lambda expressions are added in the new Java 8, which is an exciting language change. The code designed with it will be more concise and readable. Most importantly, the amount of code will be reduced.
Powerful Stream API
The improvement of collections is also a highlight of Java 8, and the core component that makes collections better and better is "Stream". It is similar to Java InputStream and OutputStream in io package are completely different concepts. It is a new concept. Don't confuse them.
Easy parallel
Parallel flow is to divide a content into multiple data blocks and process each data block with different threads.
Java 8 optimizes the parallel flow, and we can easily operate the data in parallel.
Minimize null pointer differences
The Optional class is introduced into the class of Java 8 to wrap the object to solve the NullPointerException.
Lambda expression
What is a Lambda expression?
Lambda completely replaces anonymous inner classes. Lambda is a function expression composed of parameters, arrow symbols and method calls. Lambda expressions can have parameters and no parameters, return values and no return values. A lambda expression can replace the entire anonymous inner class. Lambda expressions are usually used with functional interfaces. Using lambda expressions can write more concise and flexible code. As a more compact code style, the language expression ability of Java has been improved.
Functional interface
There are four core functional interfaces in java
Interface | type | method |
---|---|---|
java.util.function.Consumer | Consumption type | void accept(T t) |
java.util.function.Supplier | Production type | T get() |
java.util.function.Function | Functional type | R apply(T t) |
java.util.function.Predicate | Assertion type | boolean test(T t) |
There can only be one abstract method in a functional interface, and the special interface is usually used with Lambda expressions.
Example:
@FunctionalInterface public interface MyLambda { //There can only be one abstract method String test(String name); }
Syntax format of Lambda expression
Premise:
Operators introduced in Java 8: - > (arrow operator)
->The arrow operator divides the Lambda expression into two parts
Left: parameter list
Right: the implementation of the method (only represents the implementation of the method)
There is no need to specify the data type in the parameter list, and the jvm will infer the type according to the context.
()-> Method calling code
Use of Lambda expressions
Lambda expression sub whole represents the original whole anonymous function. However, many abstract methods in an abstract class or interface cannot be implemented like anonymous functions. It can only be used in the case of an abstract class or interface with only one abstract method. For the case of multiple abstract methods, please refer to the next chapter [functional methods].
Lambda doesn't have a very fixed way of writing. However, its changes are inseparable from its origin, that is, the left side must be parameters and the right side must be method execution. The parameters on the left serve the methods on the right. Several situations are listed below.
No parameter, no return value.
//No parameter, no return value. public static void test() { //The run method is implemented Runnable runnable = () -> System.out.println("Lambda"); runnable.run();//Lambda }
No parameter, return value.
// String test(); Abstract methods implemented MyLambda myLambda = () -> { return "lambda"; }; System.out.println(myLambda.test());
There is one parameter and no return value
When there is only one parameter, parentheses can be omitted. But usually, we should write parentheses for ease of reading.
// System.out.println(x) is a hypothetical method implementation, Consumer consumer = (x) -> System.out.println(x); consumer.accept("Lambda expression");
There is a parameter with a return value
// String test(String name); Implemented abstract methods MyLambda myLambda = (a) -> { return a; }; System.out.println(myLambda.test("Lambda")); }
There are two or more parameters and return values.
Comparator comparator = (x,y) -> {return Integer.compare((int)x,(int)y);}; System.out.println(comparator.compare(1, 2));
Method reference
We usually use Lambda's method body to implement the method body of the abstract method, and this part of the implementation is usually composed of the methods already implemented in the java class library. If the contents of the method body have been implemented by other methods, but the premise is that the methods referenced in the method body must be the same as the return value and formal parameter list of the abstract method, In this case, I can use three special reference methods, which can reduce the amount of code and facilitate reading.
Object reference instance
When an object calls a method in the body of a Lambda expression.
Example:
Consumer consumer = (x) ->System.out.println(x); /*The above can be replaced by method reference System.out What you get is an object println is the referenced method, */ Consumer consumer1 = System.out::println; consumer1.accept("lambda");//lambda
Class references static methods
When a class calls a static method in the body of a Lambda expression.
Example:
Comparator comparator = (x,y) -> Integer.compare(x,y); /* Where Integer is a class and compare is a static method Can write */ Comparator comparator1 = Integer::compare;
Class reference example method
When a class calls the sample method in the body of a Lambda expression.
Premise: when the first parameter in the parameter list is the caller of the instance method and the second parameter is the parameter of the instance method,
Example:
BiPredicate biPredicate = (x,y) -> x.equals(y); /* In the above method, the first parameter in the parameter list is used to call the method to pass another parameter, x Instance method for object equals() */ BiPredicate biPredicate1 = Object::equals;
Constructor reference
We usually use Lambda's method body to implement the method body of the abstract method. When this part of the implementation contains the operation of the new object, we can use the constructor reference. When there are multiple constructor overloads, when using the constructor reference, java will select the constructor matching the extraction method for us, and java will infer according to the generic type of the variable type. This can reduce the amount of code and make it easy to read.
Example:
Supplier supplier = () -> new Employee(); /* At this time, the Employee may have multiple overloads and generic inference. */ Supplier<Employee> supplier1 = Employee::new; supplier1.get();
Stream API
java.util.stream.Stream interface is a brand-new API provided in java8. Stream stream mainly uses Lambda expression implementation method in stream to perform various intermediate operations for data,
It is convenient for us to get the desired results from the original data.
Create Stream stream
- You can use the stream() or parallstream() provided by the Collection series Collection.
List list = new ArrayList(); Stream stream = list.stream(); Stream stream1 = list.parallelStream();
- Get the array stream through the static method stream() in Arrays
User[] user = new User[10]; Arrays.stream(user);
- Through the static method of() in the Stream class
Stream<String> stream = Stream of("aa","bb","cc");
Intermediate operation
Screening and slicing
method | summary |
---|---|
Stream filter(Predicate<? super T> predicate) | Returns a stream consisting of elements of this stream that match this given predicate. |
Stream limit(long maxSize) | Returns a stream composed of elements of this stream. The truncated length cannot exceed maxSize. |
Stream skip(long n) | After discarding the first N element of the stream, the stream composed of the n elements of the stream is returned. |
Stream distinct() | Returns a stream composed of different elements of the stream according to Object.equals(Object)). |
Example:
List<User> list = Arrays.asList( new User("Li Si", 41,false), new User("Wang Wu", 60,false), new User("March", 22,true), new User("Zhang San", 53,false), new User("Sun Yi", 61,true), new User("Ge Ba", 85,false) ); Stream<User> stream = list.stream(); Stream<User>stream1 = stream .filter( (user) -> { return user.getAge()>20 ;})//Filter to exclude some qualified elements in the flow .skip(2)//Discard some data, .limit(3)//Truncation makes the filtered results less than a few .distinct();//De duplication. The elements participating in de duplication need to implement hashCode and equals stream1.forEach(System.out::println);
mapping
method | summary |
---|---|
Stream map(Function<? super T,? extends R> mapper) | Returns a stream consisting of the results of the elements that the given function applies to this stream., Convert elements to other forms or extract information. Receive a function as an argument, which is applied to each element and mapped to a new element |
Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper) | Returns a stream that replaces the result of each element of the stream with the content of the mapping stream generated by applying the provided mapping function to each element. Take a function as a parameter, replace each value in the stream with another stream, and then connect all streams into one stream |
Example:
//This example is incomplete List l = Arrays.asList("a","b","c","d","e"); Stream stream = l.stream() .map((str) -> str.toUpperCase()); Stream stream1 = l.stream() .map(filterMap);
sort
method | summary |
---|---|
Stream sorted() | Returns a stream consisting of the elements of this stream, sorted in natural order. |
Stream sorted(Comparator<? super T> comparator) | Returns the stream composed of the elements of the stream, sorted according to the provided Comparator. |
Example:
List l = Arrays.asList("a","d","b","c","e"); l.stream() .sorted()// Natural sorting .forEach(System.out::println); //Custom sorting
termination
Find and match
method | summary |
---|---|
boolean allMatch(Predicate<? super T> predicate) | Check that all of these elements match |
boolean anyMatch(Predicate<? super T> predicate) | Check to see if at least one element matches |
boolean noneMatch(Predicate<? super T> predicate) | Check that no elements match |
Optional findFirst() | Returns the first element |
Optional findAny() | Returns any element in the current stream |
long count() | Returns the total number of elements in the stream |
Optional max(Comparator<? super T> comparator) | Returns the maximum value in the stream |
Optional min(Comparator<? super T> comparator) | Returns the minimum value in the stream |
Reduction and collection
You can combine the elements in the flow repeatedly to get a value. For example, add all the numeric elements in an array
method | summary |
---|---|
Optional reduce(BinaryOperator accumulator) | Use the associated accumulation function to perform reduction on the elements of this stream and return Optional (if any) describing the reduced value. |
T reduce(T identity, BinaryOperator accumulator) | Use the provided identity value and associated accumulation function to perform reduction on the elements of this flow and return the reduced value. |
U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator combiner) | Perform reduction on the elements in this flow, using the provided identity, accumulation and combination functions. |
<R,A> R collect(Collector<? super T,A,R> collector) |
Reduction example:
List l = Arrays.asList(1,2,3,4,5); l.stream().reduce(0,(x,y) -> x+y);//Take 0 as the starting value. After adding it to the starting value, the resulting value is x, and then add it to other values
Collection example:
list.stream() .map(User::getName)//Take out all names .collect(Collectors.toList());//Put the collected elements into the List list.stream() .map(User::getName)//Take out all names .collect(Collectors.toCollection(HashSet::new));//Put the collected elements into the specified container list.stream() .collect(Collectors.groupingBy(User::getSxe));//grouping list.stream() .collect(Collectors.groupingBy(User::getSxe), Collectors.groupingBy(Regroup rules));//After grouping, the group is grouped again list.stream() .collect(Collectors.groupingBy(Satisfied and unsatisfied));//Partition elements, true and false
Parallel stream and serial stream
Parallel flow is a flow that divides a content into multiple data blocks and processes each data block with different threads. Java 8 optimizes parallelism, and we can easily operate data in parallel. The Stream API can declaratively switch between parallel and sequential streams through parallel() and sequential(). Column, such as splitting a complex task according to the critical value (no splitting rule), pushing it into the thread queue, and finally join ing and merging the results obtained by the split tasks,
Optional
Java. util. The Optional class is a container class that represents the existence or nonexistence of a value. Originally, null was used to represent the nonexistence of a value. Now Optional can better express this concept. And you can avoid null pointer exceptions.
Common methods:
method | summary |
---|---|
static Optional of(T value) | Returns an Optional that is not null. If it is null, a null pointer exception will be thrown |
static Optional empty() | Returns an empty Optional container that does not contain any elements |
static Optional ofNullable(T value) | If the passed in parameter is null, an empty Optional container is returned; otherwise, an Optional container containing this value is returned |
boolean isPresent() | Determine whether there is a value in this optional container |
T orElse(T other) | If this optional container contains a value, the value in the container is returned; otherwise, the specified value is returned |
T orElseGet(Supplier<? extends T> other) | If this optional container contains a value, the value in the container is returned; otherwise, the result of the get operation of this value is returned |
Optional map(Function<? super T,? extends U> mapper) | If the result of this function is not null and does not contain a value, an empty Optional container containing no elements is returned; otherwise, an Optional container containing the processing result of this function is returned |
Optional flatMap(Function<? super T,Optional> mapper) | If the result of this function is not null and does not contain a value, an empty Optional container without any elements is returned; otherwise, a value of Object type containing the processing result of this function is returned |
Example:
import java.util.Optional; public class OptionalTest { public static void main(String[] args) { /*Returns an empty Optional container that does not contain any elements*/ Optional optional1 = Optional.empty(); /*If the parameter passed in is null, an empty Optional container will be returned; otherwise, an Optional container containing this value will be returned*/ Optional.ofNullable(null); /*Returns an Optional that is not null. If it is null, a null pointer exception will be thrown*/ Optional optional = Optional.of(null); /*Determine whether there is a value in this optional container*/ optional.isPresent(); /*If this optional container contains a value, the value in the container is returned; otherwise, the specified value is returned*/ optional.orElse(new User()); /*If this optional container contains a value, the value in the container is returned; otherwise, the result of the get operation of this value is returned*/ optional.orElseGet(() -> new User()); /*If the result of this function is not null and does not contain a value, an empty Optional container without any elements is returned, Otherwise, an optional container containing the processing results of this function is returned*/ optional.map((e) -> e.toString()); /*If the result of this function is not null and does not contain a value, an empty Optional container without any elements is returned, Otherwise, a value of Object type containing the processing result of this function is returned*/ optional.flatMap((e) -> e.toString()); } }
Interface
In Java 8, new functions are provided for interfaces: default methods and static methods with implementation.
.
Default method
"Class first" principle of interface default method
When a default method is defined in an interface and a method with the same name is defined in another parent class or interface, the method in the parent class will be selected.
If a parent class provides a concrete implementation, the default method with the same name and parameters in the interface will be ignored. If a parent interface provides a default method and another interface provides a method with the same name and parameter list (whether the method is the default method or not), the method must be overridden to resolve the conflict.
public interface myInterface { public default String a(){ return "square accounts in every detail"; } }
Static method
The processing rules for static methods and default methods with the same name are the same.
public interface myInterface { static void b(){ } }
New time date API
Java 8 brings us a new time API. Different from the past time API, the new time API has more convenient operation, less code, high readability, can perform mathematical operations, and there is no thread safety problem.
Main related categories:
class | summary |
---|---|
java.time.LocalDate | Included hour minute second date object |
java.time.LocalTime | Date object containing year month day, and other date fields, such as date, day of the week, and week |
java.time.LocalDateTime | Time Date object containing year month day hour minute second |
java.time.Instant | Instant on the timeline (timestamp) |
java.time.Duration | This class establishes quantity or time in seconds and nanoseconds, (time) |
java.time. Period | Establish quantity or time quantity in year, month and day, (date) |
java.time.temporal | The adjuster is a key tool for modifying time objects |
java.time.DateTimeFormatter | Formatter for printing and parsing date time objects. |
java.time. ZonedDate/ZonedTime/ZonedDateTime | time zone |
java.time.ZoneId | Include time zone ID |
Instances of Localdate, Localtime and Loca| Datetime classes are immutable objects. Any operation on the object will get a new immutable object, representing the date, time, date and time using the ISO-8601 calendar system respectively. They provide a simple date or time and do not contain time information several years ago. It also does not contain time zone related information.
LocalDateTime
The following only demonstrates the common methods of LocalDateTime. The methods of time class and date class are roughly the same as those of LocalDateTime class.
Example:
import java.time.*; public class MyLocalDateTime { public static void main(String[] args) { //Gets the current date from the system clock in the default time zone. LocalDateTime defaultLocalDateTime = LocalDateTime.now(); System.out.println(defaultLocalDateTime);//21-06-25T23:49:41.512 //Create a datetime object LocalDateTime localDateTime = LocalDateTime.of(2016, 1, 2,15,52,6,555); System.out.println(localDateTime);//2016-01-02T15:52:06.000000555 //Operate on time objects System.out.println(localDateTime.plusYears(5));//Plus five years System.out.println(localDateTime.minusMonths(5));//Minus may //Gets the value of the time date object System.out.println(localDateTime.getMonth());//Gets the month of the object System.out.println(localDateTime.getYear());//Gets the year of the object //Get timestamp Instant instant = Instant.now();//This time is UTC time. China time is obtained by offset System.out.println(instant); //Offset time OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));//Offset 8 hours System.out.println(offsetDateTime); //Gets the value of the difference between two times Duration duration = Duration.between(Instant.now(),instant); //Convert to seconds long duration1 = duration.toMillis();//millisecond System.out.println(duration1); } }
Time corrector
Adjust the time to a certain time
Example:
LocalDateTime localDateTime =LocalDateTime.now(); //Assign a date to a day System.out.println(localDateTime.withDayOfMonth(10)); //Get next Sunday localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); //Gets the next specified date localDateTime.with( (l) -> { LocalDateTime localDateTime1 = (LocalDateTime) l; DayOfWeek dayOfWeek = localDateTime1.getDayOfWeek(); if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {//If it's Friday return localDateTime1; } return l; } );
Format date or time
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME;//Standard for formatting LocalDateTime.now().format(dateTimeFormatter);//Format according to this standard //Create a time date object in your own format DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy MM dd HH mm ss");
time zone
Java 8 adds support for time zones. The time zones are ZonedDate, ZonedTime, and ZonedDateTime Each time zone corresponds to an ID, and the region ID is in the format of "{region} / {City}". Zoned: this class contains all the time zone information.
Example:
//Get all time zones. Set set =ZoneId.getAvailableZoneIds(); set.forEach(System.out::println); //Build a time object for the specified time zone LocalDateTime DateTime = LocalDateTime.now(ZoneId.of("US/Pacific")); //or LocalDateTime dateTime1 = LocalDateTime.now(); dateTime1.atZone(ZoneId.of("US/Pacific"));
annotation
Java 8 provides improved annotations, providing repeatable annotations that can be used for type annotations
Repeatable annotation
To make annotations edible, you need to create an annotation container.
Steps: create duplicate annotation container - > create annotation - > reuse annotation
Example of creating a repeating annotation container:
@Target({METHOD,TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotationContainer { MyAnnotation[] value(); }
Create annotation:
@Repeatable(value = MyAnnotationContainer.class) @Target({METHOD,TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { }
Reuse notes:
public class Test { @MyAnnotation @MyAnnotation public static void main(String[] args) { } }
Annotations available for types
Java 8 provides two new values for Annotation's meta Annotation @ Retention
Retention value | summary |
---|---|
TYPE_PARAMETER | It indicates that the annotation can be written in the declaration statement of type parameters, and the parameter type can be declared by type restriction on the parameters of the method |
TYPE_USE | Indicates that annotations can be used wherever types are used |
TYPE_PARAMETER:
first:
//Need to add in @ Target @Target({METHOD,TYPE, PARAMETER,TYPE_PARAMETER})
public void test(@MyAnnotation("qwe") String name){ }
TYPE_USE:
Can be used at any declared type, including annotations and enumerations.