Java 8

Java 8

Java8具備更快的運行速度,對底層的數據結構進行了修改,編程書寫代碼更少,提供了更加便利的Stream API,使用並行更簡單,減小了空指針異常的產生,提供了一個容器類減小空指針異常。java

Lambda 表達式

簡介

一種匿名函數,相似一段能夠傳遞的代碼,將代碼像傳遞數據同樣在程序中進行傳遞。Lambda表達式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。面試

示例

public class Main {

    public static  void main(String[] args) throws InterruptedException {

      Runnable runnable = new Runnable() {
          @Override
          public void run() {
              System.out.println("This is a inner class");
          }
      }; //匿名內部類
       
        Thread thread = new Thread(runnable);
        thread.start();

        Runnable runnable_new = () -> System.out.println("This is a Lambda!");
        Thread thread_new = new Thread(runnable_new);
        thread_new.start();
        
        System.out.println("------------------");
    }
}

語法

Lambda表達式中引入了 -> 操做符,箭頭操做符的左側對應參數列表,箭頭右側爲須要執行的功能,須要「函數式接口」支持,即接口中只有一個抽象方法,可使用@FuctionalInterface修飾,增強檢查。算法

int i = 8;
Runnable runnable = () -> System.out.println("This is implement" + i);

@FunctionalInterface
public interface Test<T,R>{
  public void method();
  public void method(int i);
  public int    method(int i,int j); 
  public boolean method(int i,float j);
  public R method(T t1,T T2);
}//僅做爲舉例 如下對每種狀況具體進行了實現。

Test test;

//無參無返回值
test = () -> System.out.println("This is implement");

//單個參數無返回值
test = (i) -> System.out.prinln("This is i" + i);
test = x -> System.out.println("This is i" + i);

//兩個參數返回值
Test test = (i,j) -> {
  System.out.prinln("This is i" + i);
  System.out.prinln("This is i" + j);
  return i+j;
}

//多個參數單條語句返回值
Test test = (i,j) -> i+j;
Teat test =(int i,float j) -> !(i+j);

//泛型
(i,j) -> i+j;

函數式接口

Lambda表達式須要依賴函數式接口,所以,Java8中內置了多種接口,簡介四種核心函數式接口。編程

消費型接口

Consumer<T>
    void accept(T t);

提供型接口

Supplier<T>
    T get();

函數式接口

Function<T,R>
    R apply(T t);

判斷型接口

Predicate<T>
    boolean test(T t);

其餘接口

BiFunction<T,U,R>
    R apply(T t,U u);

UnaryOperator<T>
    T apply(T t);

BinaryOperator<T>
    T apply(T t1,T t2);

ToIntFunction<T>
ToLongFunction<T>
ToDubleFunction<T>
//返回int、long、double

IntFunction<R>
LongFunction<R>
DoubleFunction<R>
//返回R

示例

public void hello(String name,Consumer<String> consumer){
        consumer.accept(name);
    }

public String getDate(String data, Supplier<String> supplier){

        return data +": "+ supplier.get();
    }

public String resoleString(String string, Function<String,String> function)
{
        return function.apply(string);
    }

public List<String> filterString(List<String> list,Predicate<String> predicate){
        List<String> stringList= new ArrayList<>();

        for (String string : list){
            if(predicate.test(string)){
                stringList.add(string);
            }
        }
        return stringList;
    }

 @Test
public void test(){
hello("Wang",(name) -> System.out.println("Hello ! I am " + name));
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
 String now =  getDate("Now",() -> {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(d);
         });
System.out.println(now);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
System.out.println("\tThis is a String with blank!        ");
String result = resoleString("\t\t\tThis is a String with blank!        ", (string) -> string.trim());
result = resoleString(result, (string) -> string.substring(5,20));
System.out.println(result);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

List<String> list = Arrays.asList("1234","abcd","http","a","Java and Oracle");
 list =  filterString(list,(s) -> s.length() > 5);
 for (String string : list)
 System.out.println(string);
}

方法引用與構造器引用

Lambda 體中已經實現了的方法,能夠進行使用,使用中只要遵循接口參數列表與構造或方法的參數返回值對應便可,帶給你全新的體驗。api

使用方法

  • 對象 :: 實例方法名
  • 類 :: 靜態方法名
  • 類 :: 實例方法名
Consumer<String> consumer = (x) -> System.out.println(x);

Consumer<String> consumer = System.out::println;
//實現方法的參數列表和引用方法必須保持一致

Integer integer = new Integer(10);

Supplier<Integer> supplier = integer::toString;
 
Supplier<ExecutorService> serviceSupplier= Executors::newCachedThreadPool;

BiPredicate<String,String> predicate = String::equals; //等效於(x,y) -> x.equals(y);
/*      哈哈哈  這仍是Java嗎?  哈哈哈*/                                           //          a.method(b) 纔可以使用
  • 類名 :: new
Supplier<Integer> integer = Integer::new;
//無參構造器

Function<int,Integer> integer = Integer::new;
//一個參數構造器
//構造器的選擇取決於Function中的方法參數,參數列表與構造器必須對應!
  • 類型 :: new
Function<Integer,String[]> function = (10) -> new String[x];

Function<Integer,String[]> function = String[]::new;

Stream API

Stream 不是集合元素,它不是數據結構並不保存數據,它是有關算法和計算的,它更像一個高級版本Iterator。原始版本的Iterator,用戶只能顯式地一個一個遍歷元素並對其執行某些操做;高級版本的 Stream,用戶只要給出須要對其包含的元素執行什麼操做,好比 「過濾掉長度大於 10的字符串」、「獲取每一個字符串的首字母」等,Stream 會隱式地在內部進行遍歷,作出相應的數據轉換,數據源自己能夠是無限的。數組

圖 1. 流管道的構成

獲取方式

  • 從 Collection 和數組
    • Collection.stream()
    • Collection.parallelStream() 並行流!在執行迭代時是多線程完成的!
    • Arrays.stream(T array) or Stream.of()
  • 從 BufferedReader
    • java.io.BufferedReader.lines()
  • 靜態工廠
    • java.util.stream.IntStream.range()
    • java.nio.file.Files.walk()
  • 本身構建
    • java.util.Spliterator
  • 其餘方式
    • Random.ints()
    • BitSet.stream()
    • Pattern.splitAsStream(java.lang.CharSequence)
    • JarFile.stream()

示例

//使用方法
        List<String> list = Arrays.asList("1234","abcd","http","a","Java and Oracle");

        Stream<String> stream = list.stream();

        int[] ints = new int[20];

        IntStream intStream = Arrays.stream(ints);

        final Stream<int[]> intsStream = Stream.of(ints);

        Stream<Integer> integerStream = Stream.iterate(0, (seed) -> seed+2);
        integerStream.limit(10).forEach(System.out::println);

        Stream.generate(() -> Math.random()).limit(10).forEach(System.out::println);

中間操做

/*過濾、切片*/
filter
從流中排除指定元素
limit
截斷流,限定流中元素個數
skip(n)
跳過n各元素,超過流元素個數,這返回空流
distinct()
去除重複元素
//鏈式調用中未執行終止操做時(forEach(...)),不會執行任何操做。
//當結果已經知足條件,則不繼續執行後方篩選條件,即具有短路特色。

/*映射*/
map(Function<T t,R r>)
將函數應用到每一個元素中,並將結果映射爲一個新的參數
flatmap
經函數做爲參數應用到每一個元素上,返回流鏈接造成的新流。

/*排序*/
sorted()
sorted((a,b) -> a>b?a:b)
  
/* 想到前段時間阿里的面試題
 * 一個巨大的數組統計每一個數字的出現次數
 */
@Test
public void testMap(){

   int a[]=new int[1000];

   for(int i=0;i<10000;i++){
        a[i]=(int) ( Math.random() *100 );
   }//模擬數組

   final IntStream stream = Arrays.stream(a);

   stream.distinct().sorted().forEach((i) ->{
        System.out.print("This is "+i+ "  count : ");
        long count = Arrays.stream(a).filter((num) -> num == i).count();
        System.out.print(count +"\n");
        });
    }

終止操做

##查找匹配
allMach
#是否匹配全部元素
anyMatch
#至少匹配一個元素
noneMatch
#是否沒有匹配全部元素
findFirst
#返回匹配的第一個元素
findAny
#隨機返回一個元素
count
#統計元素個數
max
#返回最大元素
min
#返回最小元素

##歸約
reduce(初始值,(下一次執行初始值,流中的元素))
Optional<Double> option = employees.stream().map(Employee::getSalary).reduce(Double::sum);
#####map-reduce模式#####
#將流中的元素反覆匹配執行操做

##收集
collect
#按照必定方式,進行結果收集,即將結果收集起來,可使用一個工具類Collectors
employee.stream().map(Employee::getNmae).collect(Collectors.toList());
#最終返回值一個List<String> 列表,存儲姓名屬性
Collectors.groupby
#分組
Collectors.summarizingDoutble
#數據處理方式
Collectors.joining
#字符串

並行流&串行流

Fork/Join框架

將任務分拆成多個小任務,細分到沒法再繼續分,執行後將全部的結果進行合併獲得結果,在併發包的文章裏,有寫到過,也舉了一個計算的例子,這個框架的特色就是,當任務進行拆分後,採用工做竊取模式,能夠提升計算時對CPU的利用率。工做竊取模式即當前隊列沒法獲取任務時,將去一個其餘拆分隊列的任務進行執行。安全

並行流
List.stream().parallelStream()
//執行處理時底層使用Fork/Join框架

接口默認方法與靜態方法

原接口中只能有全局靜態常量和抽象方法,在java8中能夠給接口添加添加默認方法。默認方法衝突時繼承大於實現多實現必須重寫衝突默認方法。接口能夠書寫靜態方法,使用時,直接使用接口對象調用。bash

public interface NewInterface{
  default String getDefaultMethod(){
    return "This is a default Method";
  }
  public static void getStaticMethod(){
    System.out.println("This is a static method from a interface !");
  }//NewInterface.getStaticMethod()
}

時間API

原時間相關api存在線程安全問題,使用起來較爲複雜,java8中添加全新的時間api,多線程能夠直接使用,線程安全。數據結構

java.time
#日期
java.time.chrono
#特殊時間記錄方式
java.time.format
#日期格式化
java.time.temporal
#運算推算日期
java.time.zone
#時區相關設置

操做

//使用時間
@Test
public void testNewDate(){
  //LocalDate LocalTime LocalDateTime
  LocalDateTime  localDateTime = LocalDateTime.now();
  System.out.println(localDateTime);
  -----------------------------------
  localDateTime = LocalDateTime.of(2018,9,13,23,44);
  System.out.println(localDateTime);
  -----------------------------------
  localDateTime = localDateTime.plusYears(2);
  System.out.println(localDateTime);
  -----------------------------------
  localDateTime = localDateTime.minusYears(2);
  System.out.println(localDateTime);
}
//時間戳
@Test
public void testTimeInstant(){
  //Unix 1970.1.1 0.0.0 到如今毫秒 協調世界時
  Instant instant = Instant.now();
  //設置時間偏移量
  instant.atOffset(ZoneOffset.offHours(8));
  //獲取毫秒
  System.out.println(instant.toEpochMilli());
  //運算
  Instant.ofEpochSecond(60);//1971.1.1 0.1.0
  //計算間隔
  Duration duration = Duration.between(instant_end , instant_begin);
  
  Period period = Period.between(localDate_end , localDate_begin);
  
}

其餘

註解

java8中能夠對方法進行重複註解。多線程

@Repeatable(MoreAnnotations.class)
public @interface MoreAnnotation{
  String value9() default "註解";
}

public @interface MoreAnnotations{
  MoreAnnotation[] values();
}

@MoreAnnotation
@MoreAnnotation
@MoreAnnotation
public void method(){}

類型註解

private @NonNull Object obj = null
//不支持

HashMap

碰撞產生的鏈表在長度大於8時將會產生紅黑樹

hashMap內存結構圖

ConcurrentHashMap

原16段併發鎖改成CAS算法,同時也具有紅黑樹。

內存模型

相關文章
相關標籤/搜索