New features of Java 8 are carefully organized

Keywords: Java Lambda jvm Maven

Preface

More and more projects have been used Java 8 No doubt, Java 8 It is the most important version of Java since Java 5 (released in 2004). This version contains more than a dozen new features, including languages, compilers, libraries, tools, and JVM. In this article, we will learn about these new features and illustrate with practical examples what scenarios are suitable for use.

Quotation: This article refers to these two articles, to make their own understanding, organized into a new feature article of Java 8 which is the easiest to understand. A few chapters may be consistent, but they are definitely not plagiarism, just for the integrity of the article. Most of the commonly used places add my own understanding and examples.

https://blog.csdn.net/yczz/article/details/50896975

https://blog.csdn.net/maosijunzi/article/details/38658095

Suitable for Readers and Targets

Target population

  • Suitable for students who have used lambda expressions, want to understand thoroughly
  • Learn about the new specificities of Java 8

target

  • Knowing the functional interface and Lambda expression of Java 8, you can customize the functional interface.
  • Use of method references
  • Static and default methods of interfaces
  • New classes and expiration compared to previous versions
  • Use of Stream API

1. New features of the Java language

Java 8 lambda is really a lot easier to use, but it also makes it difficult for first-time acquaintances to read, which is actually why you are not used to it. Many languages have supported Lambda expressions from the beginning, such as Groovy,Scala and so on.

1.1 Lambda expressions and functional interfaces

Before Java 8, we wanted a method to interact with users, such as using local variables in the method; at this time, we could only use interfaces as parameters to enable users to implement the interface or use anonymous internal classes to pass local variables to users through the interface method.

Disadvantage of traditional anonymous internal classes: bloated code, difficult to read

Lambda expression

Lambda expressions pass functions as parameters to a method or code itself as data processing.

Grammatical Format:

  • Comma-separated parameter list
  • > symbol
  • And statement blocks
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

Equivalent to

List<String> list = Arrays.asList( "a", "b", "d" );
for(String e:list){
    System.out.println(e);
}

If the statement block is more complex, wrap it in {}

Arrays.asList( "a", "b", "d" ).forEach( e -> {
    String m = "9420 "+e;
    System.out.print( m );
});

Lambda is essentially a modification of an anonymous inner class, so the variables it uses are implicitly converted to final

String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach( 
    e -> System.out.print( e + separator ) );

Equivalent to

final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach( 
    e -> System.out.print( e + separator ) );

Lambda's return values and parameter types are inferred by the compiler, and no definitions need to be displayed. If there is only one line of code, no return statement can be written.

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

Equivalent to

List<String> list = Arrays.asList("a", "b", "c");
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});

Functional interface

  • There can only be one interface method in the interface.
  • You can have static methods and default methods
  • Use the @FunctionalInterface tag
  • The default method can be overridden
@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();
 
    default void defaultMethod() {            
    }
    
    static void staticMethod(){
    }
}
private interface Defaulable {
    // Interfaces now allow default methods, the implementer may or 
    // may not implement (override) them.
    default String notRequired() { 
        return "Default implementation"; 
    }        
}
 
private static class DefaultableImpl implements Defaulable {
}
 
private static class OverridableImpl implements Defaulable {
    @Override
    public String notRequired() {
        return "Overridden implementation";
    }
}

// It can also be covered by interfaces. 
public interface OverridableInterface extends Defaulable{
    @Override
    public String notRequired() {
        return "interface Overridden implementation";
    }
}

Because the implementation of default methods on JVM provides support at the bytecode level, it is very efficient. The default method allows improved interfaces without breaking existing inheritance systems. The application of this feature in official libraries is to add new methods to the java.util.Collection interface, such as stream(), parallelStream(), forEach(), removeIf(), and so on.

Existing Java 8-defined functional interfaces

We don't need to define our own functional interfaces. Java 8 has provided us with a large number of default functional interfaces, which are basically enough. You can see all default functional interfaces in the java.util.function directory of rt.jar package, which can be roughly divided into several categories.

  • Function < T, R > T as input and R as output
  • Predicate < T > T as input, returns the output of boolean value
  • Consumer < T > T as input, no output
  • Supplier < R > No input, R as output
  • BinaryOperator < T > two T as input and T as output
  • Unary Operator < T > is a variant of Function, and the input and output are T.

Others are the various extensions of the above, just for more convenient use. Here's an example, you can use it as a normal interface, which is imported by users using Lambda.

// hello world example
Function<String,String> function = (x) -> {return x+"Function";};
System.out.println(function.apply("hello world"));    // hello world Function

UnaryOperator<String> unaryOperator = x -> x + 2;
System.out.println(unaryOperator.apply("9420-"));    // 9420-2

// Examples of judging whether an input value is even
Predicate<Integer> predicate = (x) ->{return x % 2 == 0 ;};
System.out.println(predicate.test(1));                // false

// This has no return value
Consumer<String> consumer = (x) -> {System.out.println(x);};
consumer.accept("hello world ");                    // hello world

// This has no input. 
Supplier<String> supplier = () -> {return "Supplier";};
System.out.println(supplier.get());                    // Supplier

// Find large numbers
BinaryOperator<Integer> bina = (x, y) ->{return x > y ? x : y;};
bina.apply(1,2);                                    // 2 

1.2 Method Reference

Method references allow developers to directly refer to existing methods, Java class constructors, or instance objects. Method references and Lambda expressions are used together to make the construction of Java classes look compact and concise without much complex template code.

public static class Car {
    public static Car create( final Supplier< Car > supplier ) {
        return supplier.get();
    }              
 
    public static void collide( final Car car ) {
        System.out.println( "Collided " + car.toString() );
    }
 
    public void follow( final Car another ) {
        System.out.println( "Following the " + another.toString() );
    }
 
    public void repair() {   
        System.out.println( "Repaired " + this.toString() );
    }
}

The first method refers to the type of constructor reference, and the grammar is Class::new, or more generally: Class < T >:: new. Note: This constructor has no parameters.

final Car car = Car.create( Car::new );

Equivalent to

Car car = Car.create(() -> new Car());

The second method refers to the type of static method reference and the grammar is Class::static_method. Note: This method accepts a Car type parameter.

cars.forEach( Car::collide );

forEach Archetype forEach(Consumer<? super T> action) Used is Consumer Only parameters, no return value; this parameter T Namely car Type, because yes cars.forEach Well, so the method reference above is equivalent to

cars.forEach(car -> Car.collide(car));

The third method refers to a reference to a member method of a class, and the grammar is Class::method. Note that this method does not define a reference:

cars.forEach( Car::repair );

It is equivalent to

cars.forEach(car -> car.repair());

1.3 Repeated annotations

Since the introduction of Java 5 annotation Since then, this feature has become very popular and widely used in various frameworks and projects. However, there is a big limitation to annotations: you can't use the same annotation many times in the same place. Java 8 breaks this limitation by introducing the concept of repetitive annotations, allowing multiple use of the same annotation in the same place.

Using the @Repeatable annotation in Java 8 to define duplicate annotations, in fact, this is not a language level improvement, but a trick made by the compiler, and the underlying technology is still the same. The following code can be used to illustrate:

@Target( ElementType.TYPE )
@Retention( RetentionPolicy.RUNTIME )
@Repeatable( Filters.class )
public @interface Filter {
    String value();
};

@Filter( "filter1" )
@Filter( "filter2" )
public interface Filterable {        
}

public static void main(String[] args) {
    for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
        System.out.println( filter.value() );
    }
}

As we can see, the Filter class here is decorated with @Repeatable(Filters.class) annotations, which are containers for Filter annotations, and the compiler tries to shield developers from these details. In this way, the Filterable interface can be annotated with two Filters (no information about Filters is mentioned here).

In addition, the reflection API provides a new method: getAnnotationsByType(), which returns a type of duplicate annotation, such as Filterable.class.getAnnoation(Filters.class), which returns two instances of Filter.

1.4 Better Type Inference

Java 8 compiler has a great improvement in type inference. In many scenarios, the compiler can deduce the data type of a parameter, which makes the code more concise. The example code is as follows:

public class Value< T > {
    public static< T > T defaultValue() { 
        return null; 
    }
 
    public T getOrDefault( T value, T defaultValue ) {
        return ( value != null ) ? value : defaultValue;
    }
}
public class TypeInference {
    public static void main(String[] args) {
        final Value< String > value = new Value<>();
        value.getOrDefault( "22", Value.defaultValue() );
    }
}

The type of the parameter Value.defaultValue() is derived by the compiler without explicit specification. There will be compilation errors in this code in Java 7 unless you use Value. <String>defaultValue()

1.5 Widening the Application Scenario of Annotations

Java 8 broadens the application scenario of annotations. Nowadays, annotations can be used on almost any element: local variables, interface types, superclasses and interface implementation classes, and even on exception definitions of functions. Here are some examples:

package com.javacodegeeks.java8.annotations;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;
 
public class Annotations {
    @Retention( RetentionPolicy.RUNTIME )
    @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )
    public @interface NonEmpty {        
    }
 
    public static class Holder< @NonEmpty T > extends @NonEmpty Object {
        public void method() throws @NonEmpty Exception {            
        }
    }
 
    @SuppressWarnings( "unused" )
    public static void main(String[] args) {
        final Holder< String > holder = new @NonEmpty Holder< String >();        
        @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();        
    }
}

ElementType.TYPE_USER and ElementType.TYPE_PARAMETER are two new annotations added to Java 8 to describe the usage scenarios of annotations. The Java language has also made corresponding changes to identify these new annotations.

2. New features of Java compiler

Java 8 began to officially support parameter names, and finally did not need to read class bytecodes to get parameter names, which is particularly useful for people who often use reflection.

In Java 8, this feature is turned off by default, and parameters need to be turned on to get parameter names:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <compilerArgument>-parameters</compilerArgument>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
</plugin>

3. New features of JVM

Using Metaspace( JEP 122 ) Instead of PermGen space. For JVM parameters, use - XX:MetaSpaceSize and - XX:MaxMetaspaceSize instead of - XX:PermSize and - XX:MaxPermSize.

4. New features of Java official Libraries

Java 8 adds many new tool classes (date/time classes) and extends existing tool classes to support modern concurrent programming, functional programming, etc. This chapter refers to the original text and extracts common functions.

4.1 Streams

Streams operations are divided into intermediate operations and late operations. Intermediate operations return a new Stream, which only records the operations to be done and does not actually execute. Late operations actually traverse the list and perform all operations.

Another value of Stream is that it supports parallel processing.

Stream API simplifies the operation of collections and extends the functions of grouping, summation, mapReduce, flatMap, sorting and so on. The following list of commonly used functions in projects will use frequency sorting.

  1. Prepare an object for the following example test
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Vehicle {
    //Frame number
    private String vin;
    // Owner's mobile phone number
    private String phone;
    // Name of owner
    private String name;
    // Vehicle Rental Company
    private Integer companyId;
    // Personal score
    private Double score;
    //Installed device list imei, separated by commas
    private String deviceNos;
}
  1. Prepare some vehicle data
static List<Vehicle> vehicles = new ArrayList<>();

@Before
public void init(){
    List<String> imeis = new ArrayList<>();
    for (int i = 0; i <5 ; i++) {
        List<String> singleVehicleDevices = new ArrayList<>();
        for (int j = 0; j < 3; j++) {
            String imei = RandomStringUtils.randomAlphanumeric(15);
            singleVehicleDevices.add(imei);
        }
        imeis.add(StringUtils.join(singleVehicleDevices,','));
    }
    vehicles.add(new Vehicle("KPTSOA1K67P081452","17620411498","9420",1,4.5,imeis.get(0)));
    vehicles.add(new Vehicle("KPTCOB1K18P057071","15073030945","Zhang Ling",2,1.4,imeis.get(1)));
    vehicles.add(new Vehicle("KPTS0A1K87P080237","19645871598","sanri1993",1,3.0,imeis.get(2)));
    vehicles.add(new Vehicle("KNAJC526975740490","15879146974","Plum seed",1,3.9,imeis.get(3)));
    vehicles.add(new Vehicle("KNAJC521395884849","13520184976","Yuan Shao",2,4.9,imeis.get(4)));
}

4.1.1 forEach traversal Collection data

vehicles.forEach(vehicle -> System.out.println(vehicle));

//This allows you to traverse print
vehicles.forEach(System.out::println);

4.1.2 forEach traverses Map data

Map<String,Integer> map = new HashMap<>();
map.put("a",1);map.put("b",2);map.put("c",3);

map.forEach((k,v) -> System.out.println("key:"+k+",value:"+v));

4.1.3 filter Data Filtering

// Get rid of a car with a score of less than 3
List<Vehicle> collect = vehicles.stream().filter(vehicle -> vehicle.getScore() >= 3).collect(Collectors.toList());

4.1.4 map object mapping

For a List < Object > in most cases, we only need a column in the list, or we need to convert every object in the list into other objects. In this case, map mapping can be used.

// Take out all the frame number lists
 List<String> vins = vehicles.stream().map(Vehicle::getVin).collect(Collectors.toList());

4.1.5 groupBy grouped by an attribute

// Grouping according to company Id
Map<Integer, List<Vehicle>> companyVehicles = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId));

// Ask for driver's score and sum according to company group
Map<Integer, Double> collect = vehicles.stream().collect(Collectors.groupingBy(Vehicle::getCompanyId, Collectors.summingDouble(Vehicle::getScore)));

4.1.6 sort sorted by an attribute and by multiple columns

// Single column sorting 
vehicles.sort((v1,v2) -> v2.getScore().compareTo(v1.getScore()));

// Or use the Comparator class to construct the comparator. Flow processing does not change the original list. It needs to receive the return value to get the expected results.
 List<Vehicle> collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()).collect(Collectors.toList());

// Multi-column sorting, score descending, companyId ascending
List<Vehicle> collect = vehicles.stream().sorted(Comparator.comparing(Vehicle::getScore).reversed()
                .thenComparing(Comparator.comparing(Vehicle::getCompanyId)))
                .collect(Collectors.toList());

4.1.7 flatMap Flattening Data Processing

// Find out all equipment bound to all cars
List<String> collect = vehicles.stream().map(vehicle -> {
    String deviceNos = vehicle.getDeviceNos();
    return StringUtils.split(deviceNos,',');
}).flatMap(Arrays::stream).collect(Collectors.toList());

flatMap is very suitable for List < List > or List < object []> structure and can be treated as a list; like the device list above, the structure stored in the database is comma-separated data, while the vehicle list is a list data.

4.1.8 mapReduce data processing

// Summation of total points for all drivers
Double reduce = vehicles.stream().parallel().map(Vehicle::getScore).reduce(0d, Double::sum);

4.1.9 Integrated Processing Example

// Total score
Double totalScore = vehicles.stream().parallel().map(Vehicle::getScore).reduce(0d, Double::sum);

// Check the percentage of each driver's score
List<String> collect = vehicles.stream()
    .mapToDouble(vehicle -> vehicle.getScore() / totalScore)
    .mapToLong(weight -> (long) (weight * 100))
    .mapToObj(percentage -> percentage + "%")
    .collect(Collectors.toList());

I don't know what boxed means in the original text. I hope God can help me to solve it. It's also possible without boxed.

4.2 Optional

Optional is used to solve the NullPointerException that often occurs in Java, so as to avoid the source code being polluted by various empty checks, and make the source code more concise and easier to read.

// Suppose there's an object obj, you don't know if it's empty, but you want to use its method to play with it.
Optional<T> canUseObj = Optional.ofNullable(obj);
canUseObj.ifPresent(System.out::println);        //If obj is not empty, you can use obj's method. Here's a simple output 

4.3 Date/Time API(JSR 310)

This is a good one.

4.4 Base64

For Base64, the third-party package is finally not referenced, and it can be done using the java library.

// Code
final String encoded = Base64.getEncoder().encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
// Decode
final String decoded = new String( Base64.getDecoder().decode( encoded ),StandardCharsets.UTF_8 );

4.5 JUC Toolkit Extension

Based on the new lambda expressions and step features, a new method is added for Java 8 to support focusing operations for java.util.concurrent.ConcurrentHashMap classes, and a new method is added for java.util.concurrentForkJoinPool classes to support common thread pool operations (more can be referred to). Our Concurrent Programming Course).

Java 8 also adds a new java.util.concurrent.locks.StampedLock class to support capacity-based locks, which have three models to support read and write operations (you can think of this lock as a substitute for java.util.concurrent.locks.ReadWriteLock).

In the java.util.concurrent.atomic package, a number of tool classes have been added as follows:

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder

5. New tools

Java 8 provides some new command line tools, and this section explains some of the most useful tools for developers.

Class 5.1 Dependency Analyser: jdeps

deps is a great command-line tool that shows Java class dependencies at package and class levels. It takes. class files, directories, or Jar files as input, and then outputs dependencies to the console.

We can use jedps analysis Spring Framework Library To make the results smaller, just analyze a JAR file: org. spring framework. core - 3.0.5. RELEASE. jar.

jdeps org.springframework.core-3.0.5.RELEASE.jar

This command will output a lot of results, and we'll just look at some of them: dependencies are grouped by packages, and "not found" is displayed if no dependencies are found on the classpath.

org.springframework.core-3.0.5.RELEASE.jar -> C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar
   org.springframework.core (org.springframework.core-3.0.5.RELEASE.jar)
      -> java.io                                            
      -> java.lang                                          
      -> java.lang.annotation                               
      -> java.lang.ref                                      
      -> java.lang.reflect                                  
      -> java.util                                          
      -> java.util.concurrent                               
      -> org.apache.commons.logging                         not found
      -> org.springframework.asm                            not found
      -> org.springframework.asm.commons                    not found
   org.springframework.core.annotation (org.springframework.core-3.0.5.RELEASE.jar)
      -> java.lang                                          
      -> java.lang.annotation                               
      -> java.lang.reflect                                  
      -> java.util

A little promotion

Creation is not easy, I hope you can support my open source software, and my gadgets, welcome to gitee dot star, fork, bug.

Excel General Import and Export, Supporting Excel Formula
Blog address: https://blog.csdn.net/sanri1993/article/details/100601578
gitee: https://gitee.com/sanri/sanri-excel-poi

Using template code to generate code from the database, as well as widgets that are often used in some projects
Blog address: https://blog.csdn.net/sanri1993/article/details/98664034
gitee: https://gitee.com/sanri/sanri-tools-maven

Posted by bamse on Sat, 21 Sep 2019 08:14:57 -0700