jdk1.8新特性


      jdk1.8版本是2014發布的,自java 1.5以來最具有革命性的版本了,在語言、編譯器、類庫、開發工具以及Java虛擬機等方面都帶來了不少新特性。

並且版本穩定,已經廣泛應用於企業級開發。這些新特性能夠幫助開發人員提升編碼效率,加深對java的理解,因此作為一個合格的java程序員,掌握

和理解這些新特性是很有必要的。下面開始介紹這些新特性。

  •   lambda表達式

lambda表達式是將函數作為參數進行傳遞,從而實現了函數式編程(函數式編程在js中廣泛應用),看下面一段傳統方式創建線程的代碼:

   Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable...");
                System.out.println("run....");
            }
       

利用lambda表達式可以這樣寫

Runnable runnable2 = ()->{
            System.out.println("runnable...");
            System.out.println("run....");
        };

其中 () 代表參數, {}代表函數主體。表現為 (Type1 parameter1,Type2 parameter2........)->{statment1;statmenet2;......}

什么情況適用於lambda表達式呢?答案是 :能夠接收Lambda表達式的參數類型,是一個只包含一個方法的接口,稱為函數式接口,為此jdk1.8推出了一種標記注解@FunctionalInterface

@FunctionalInterface
public interface Animal {
    String talk(String name);
}

//main
Animal animal = (name)->"animal的name是:"+name;
System.out.println(animal.talk("dog..."));

 

  •  方法引用

Lambda方法體中的內容已經有實現,可以使用方法引用。前提是

 1. Lambda體中的調用方法的參數,返回值要和該Lambda對應的函數式接口中抽象方法的參數和返回值一致

語法格式:

對象::實例方法名         Consumer<String> con = System.out:print

類::靜態方法名            Comparator<Integer> com = Integer::compare;

類::實例方法名           BiPredicate<String,String> biPredicate = String::equals; == biPredicate = (x,y)->x.equals(y);   

前提是參數列表中第一個參數是實例方法的調用者,第二個參數是實例方法的參數

或者第一個參數是實例方法的調用者,沒有第二個參數   list.stream().map(String::toUpperCase).forEach(System.out::println); == list.stream().map(x->x.toUpperCase()).forEach(System.out::println);


若對參數有任何修改,則不能使用方法引用,而需鍵入完整地lambda表達式,如下所示:

list.forEach((String s) -> System.out.println("*" + s + "*"));

  • 構造器引用

語法格式:類名::new

1.無參構造器

Supplier<Object> supplier = Object::new   == Supplier<Object> supplier = ()->new Object()

2.一個參數的構造器

Function<String,String> fun = String::new  == Function<String,String> fun = (p)-> new String(p)

 

import java.util.Arrays;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: chenzhubing
 * Date: 2019/6/27
 */
public class MyConsumer {


    public static void main(String[] args) {
       List<String> list = Arrays.asList("a","b","c");
       list.forEach(x->MyConsumer.print(x));
       list.forEach(MyConsumer::print);

       new MyConsumer().start();


    }
    public void start(){
        List<String> list = Arrays.asList("a1","b1","c1");
        list.forEach(x->{new MyConsumer().print1(x);});
        list.forEach(new MyConsumer()::print1);

    }

    public  void print1(String str){
        System.out.println(str);
    }

    public static void print(String str){
        System.out.println(str);
    }



}
  • 內置核心接口
  1.     consumer<T> 消費型接口:void accept(T t)
  2.     Supplier<T> 供給型接口:T get()
  3.     Function<T,R> 函數型接口:R apply(T t)
  4.     R apply(T t)斷言型接口:boolean test(T t)

 Consumer:有參數,無返回值

 /**
     *
     * @param param
     * @param con
     */
    public void testConsumerInterface(Integer param, Consumer<Integer> con){
        con.accept(param);
    }


   test.testConsumerInterface(10,(p)-> System.out.println(p));

  

 Supplier:無入參,有返回值

/**
     *
     * @param supplier
     * @return
     */
    public List<Integer> testSupplierInterface(Supplier<Integer>supplier){
        List<Integer> list = new ArrayList<>();
        list.add(supplier.get());
        return list;
    }

List result = test.testSupplierInterface(()->100);
result.forEach(System.out::println);

  Function:有入參,有出參

/**
     *
     * @param input
     * @param fun
     * @return
     */
    public List<String> testFunctionInterface(Integer input,Function<Integer,String> fun){
        List<String> list = new ArrayList<>();
        list.add(fun.apply(input));
        return list;

    }
result = test.testFunctionInterface(100,p->p+"hello,world");
result.forEach(System.out::println);

  Predicate : 有入參,返回值是boolean

/**
     *
     * @param input
     * @param predicate
     * @return
     */
    public List<Integer> testPredicateInterface(Integer input, Predicate<Integer> predicate){
        List<Integer> list = new ArrayList<>();
        if(predicate.test(input)){
            list.add(input);
        }
        return list;

    }

result = test.testPredicateInterface(100,p->p>10);
result.forEach(System.out::println);

  

 

  • stream

jdk1.8新推出來的stream(和IO流沒有關系)是針對Collection的增強。它專注於對集合對象進行各種非常便利、高效的聚合操作。配合lambda表達式能提升編碼效率和程序的可讀性。

1.Stream不會自己存儲元素

2.Stream不會改變源對象,會返回一個新的Stream

3.Stream操作是延遲執行的,意味着需要結果的時候才執行

public class Person {

    private String name;
    private String nickName;
    private int gender; //0-男  1-女
    private int salary; //薪水



    public String getName() {
        return name;
    }


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                ", gender=" + gender +
                ", salary=" + salary +
                '}';
    }

    public Person(){

    }

    public static Person getPerson(){
        return new Person();
    }

    public Person(String name, String nickName, int gender, int salary) {
        this.name = name;
        this.nickName = nickName;
        this.gender = gender;
        this.salary = salary;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String getNickName() { return nickName; }

    public void setNickName(String nickName) { this.nickName = nickName; }



}


 List<Person> list = new ArrayList<Person>(){
            {
                add(new Person("張三","zhangsan",0,10));
                add(new Person("李四","zhangsan",1,20));
                add(new Person("王五","wangwu",0,30));
                add(new Person("小劉","xiaoliu",1,40));
                add(new Person("三木","sanmu",0,50));

            }

        };

常用的操作有:filter,limit,skip,distinct,min,max,flatMap,sorted........................... 

 

1)min  :求集合中最小對象

 Object obj = list.stream().min((p1,p2)->(p1.getSalary()-p2.getSalary())).get();

 

2 ) max   : 求集合最大對象

 Object obj = list.stream().max((p1,p2)->(p1.getSalary()-p2.getSalary())).get();

 

3 ) filter :根據條件過濾

list.stream().filter((p)->(1==p.getGender()))

 

4 ) limit:  取集合中的前多少個元素

list.stream().filter(

(p)->(1==p.getGender())

).limit(5)

 

5 ) sorted :排序

list.stream().sorted(

(p1,p2)->p1.getNickName().compareTo(p2.getNickName())

).forEach(

x-> System.out.println(x.getName())

)

 

6)allMatch

boolean r = list1.stream().allMatch(x->x.equals("a"));
System.out.println(r);

7)anyMatch


r = list1.stream().anyMatch(x->x.equals("e"));
System.out.println(r);

8)noneMatch


r = list1.stream().noneMatch((x)->x.equals("a"));
System.out.println(r);

9)count


long count = list1.stream().count();
System.out.println(count);

 

10 )  map:  歸類,結果一般是一組數據

list1.stream().map(x->x.getSalary()).forEach(x-> System.out.println(x));     //將person中salary歸類成一組數據

List<Integer> mapList = list1.stream().map(x->x.getSalary()).map(x->x-10).collect(Collectors.toList());   //將person中的salary歸類成一組數據,並將salary-10

 

11 ) reduce: 歸約 ,用來計算結果,結果是一個數值

Integer sum = list1.stream().map(x->x.getSalary()).reduce(0,(x,y)->x+y);   //求總和,其中0是基准

int max = list1.stream().map(x->x.getSalary()).reduce(0,(x,y)->Integer.max(x,y));

 

12) collect : 收集,將處理后的結果輸出到新的集合中,如list,set,map等 ;或者返回處理的結果,如求集合的個數,平均值等

list.stream().filter().collect(Collectors.toList())

list.stream().filter().collect(Collectors.toSet())

Long count = list1.stream().filter(p->p.getGender()==0).collect(Collectors.counting());

Double sumSalary = list1.stream().collect(Collectors.summingDouble(x->x.getSalary()));

double red = list2.stream().collect(Collectors.maxBy(Double::compareTo)).get();

double red = list2.stream().collect(Collectors.minBy(Double::compareTo)).get();

Map<Double,List<Double>> map = list2.stream().collect(Collectors.groupingBy(x->x));    //分組

Map<Double,Map<Double,List<Double>>> map1 = list2.stream().collect(Collectors.groupingBy(x->x,Collectors.groupingBy(x->x)));     //多級分組

str = list1.stream().collect(Collectors.joining(",","start=","end="));  //結果集拼接

 

13 ) toMap

Map map = list1.stream().filter((p)->(1==p.getGender())).limit(2).collect(Collectors.toMap(Person::getName,Person::getNickName));  // key=name ,value=nickname

map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity()));    //key=nickname,  value = key對應的對象;注意key重復會拋出異常

map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity(),(oldValue,newValue)->newValue));   //key重復, 取新的key

map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity(),(oldValue,newValue)->oldValue));  //key重復, 取舊的key

 

  • Optional

Optional的主要用處是可以有效的避免NullPointerException,配合lambda可以減少代碼中大量的空指針判斷,總之,代碼更加優雅。

1)   創建Optional對象 :主要有兩種方式

 1.1  要求T非空,這種方式實際意義不大

Optional<T>  op  = Optional.of(T); 

1.2  可以包裝一個null的對象

Optional<T>  op = optional.ofNullable(T);

 

2)  ifPresent

op.ifPresent(p1->p1.setName("hello"));

如果T存在,則執行 p1->p1.setName("hello"),相當於

if(T != null){

p1.setName("hello");

}

 

3)  orElse

如果T存在,返回;如果T不存在,則返回orElse里面的對象

op.orElse(Person.getPerson());

等價於

if(op.ifPresent()){

return op.get();

}else{

Person.getPerson();

}

 

4)  orElseGet

如果T存在,返回;如果T不存在,則執行orElseGet里面的內容,並返回一個對象

op.orElseGet(()->{
System.out.println("helloworld");
System.out.println("sssssssssss");
return new Person();
});

  5)  orElseThrow

如果T存在,返回;如果T不存在,則執行orElseThrow里面的內容,並返回一個異常

op.orElseThrow(()->{
System.out.println("exception");
return new ArithmeticException("null");

});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM