Java8的新特性

MaximoGCU 8年前發布 | 17K 次閱讀 Java8 Java開發

來自: https://segmentfault.com/a/1190000004419611

Java語言特性系列

</div>

本文主要講Java8的新特性,Java8也是一個重要的版本,在語法層面有更大的改動,支持了lamda表達式,影響堪比Java5的泛型支持。

特性列表

  • lamda表達式( 重磅 )

  • 集合的stream操作

  • 提升HashMaps的性能

  • Date-Time Package

  • java.lang and java.util Packages

  • Concurrency

lamda表達式( 重磅 )

方法引用

/**

  • 靜態方法引用:ClassName::methodName
  • 實例上的實例方法引用:instanceReference::methodName
  • 超類上的實例方法引用:super::methodName
  • 類型上的實例方法引用:ClassName::methodName
  • 構造方法引用:Class::new
  • 數組構造方法引用:TypeName[]::new
  • Created by patterncat on 2016-02-05. */ public class MethodReference {

    @Test public void methodRef(){

     SampleData.getThreeArtists().stream()
             .map(Artist::getName)
             .forEach(System.out::println);
    

    }

    @Test public void constructorRef(){

     ArtistFactory<Artist> af = Artist::new;
     Artist a = af.create("patterncat","china");
     System.out.println(a);
    

    } }</pre>

    集合的stream操作

    /**

  • 主要接口
  • 1,predicate
  • 2,Unary/BinaryOperator:傳入參數和返回值必然是同一種數據類型
  • 3,Int/Double/LongFunction/BiFunction:函數接口并不要求傳入參數和返回值之間的數據類型必須一樣
  • 4,Int/Long/DoubleConsumer/BiConsumer:消費數據
  • 5,Int/Long/DoubleSupplier:生產數據 *
  • 主要方法:
  • 1,filter
  • 2,map
  • 3,reduce
  • 4,collect
  • 5,peek
  • -Djdk.internal.lambda.dumpProxyClasses
  • Created by patterncat on 2016-02-05. */ public class LamdaDemo {

    int[] arr = {4,12,1,3,5,7,9};

    @Test public void filter(){

     Arrays.stream(arr).filter((x) -> x%2 !=0).forEach(System.out::println);
    

    }

    @Test public void map(){

     Arrays.stream(arr).map((x) -> x * x).forEach(System.out::println);
    

    }

    @Test public void reduce(){

     Arrays.stream(arr).reduce((x,y) -> x+y).ifPresent(System.out::println);
     System.out.println(Arrays.stream(arr).reduce(-10, (x, y) -> x + y));
    

    }

    @Test public void collect(){

     List<Integer> list = Arrays.stream(arr).collect(ArrayList::new,ArrayList::add,ArrayList::addAll);
     System.out.println(list);
    
     Set<Integer> set = list.stream().collect(Collectors.toSet());
     System.out.println(set);
    
     Map<String,Artist> map = SampleData.getThreeArtists().stream()
             .collect(Collectors.toMap(a -> a.getName(),a -> a));
     System.out.println(map);
    

    }

    @Test public void peek(){

     long count = Arrays.stream(arr).filter(x -> x > 2).peek(System.out::println).count();
     System.out.println(count);
    

    }

    @Test public void average(){

     Arrays.stream(arr).average().ifPresent(System.out::println);
    

    }

    @Test public void sum(){

     System.out.println(Arrays.stream(arr).sum());
    

    }

    @Test public void max(){

     Arrays.stream(arr).max().ifPresent(System.out::println);
    

    }

    @Test public void min(){

     Arrays.stream(arr).min().ifPresent(System.out::println);
    

    }

    @Test public void sorted(){

     Comparator<Artist> asc = (x,y) -> x.getName().compareTo(y.getName());
     SampleData.getThreeArtists().stream().sorted(asc).forEach(System.out::println);
     SampleData.getThreeArtists().stream().sorted(asc.reversed()).forEach(System.out::println);
     SampleData.getThreeArtists().stream().sorted(Comparator.comparing(Artist::getName)).forEach(System.out::println);
     SampleData.getThreeArtists().stream().sorted(Comparator.comparing(Artist::getName).reversed()).forEach(System.out::println);
    
     SampleData.getThreeArtists().stream().sorted(Comparator.comparing(Artist::getName).thenComparing(Artist::getNationality)).forEach(System.out::println);
    

    }

    @Test public void groupBy(){

     Map<String,List<Artist>> rs = SampleData.getThreeArtists().stream().collect(Collectors.groupingBy(Artist::getNationality));
     System.out.println(rs);
    

    }

    @Test public void join(){

     String joinedNames = SampleData.getThreeArtists().stream().map(Artist::getName).collect(Collectors.joining(","));
     System.out.println(joinedNames);
     joinedNames.chars().mapToObj(c -> (char) Character.toUpperCase(c)).forEach(System.out::println);
    

    }

    @Test public void flatMap(){

     Set<Artist> rs = SampleData.getThreeArtists().stream().flatMap(a -> a.getMembers()).collect(Collectors.toSet());
     rs.stream().forEach(System.out::println);
    

    }

    @Test public void arrStream(){

     Arrays.stream(arr).forEach(System.out::println);
    

    }

    @Test public void then(){ // IntConsumer out = System.out::println; // IntConsumer err = System.err::println;

     IntConsumer out = (x) -> System.out.println("out consume:"+x);
     IntConsumer err = (x) -> System.err.println("err consume:"+x);
    

    // Arrays.stream(arr).forEach(out.andThen(err));

     Arrays.stream(arr).forEach(err.andThen(out));
    

    }

@Test
public void foreach(){
    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6);
    numbers.forEach(System.out::println);
}

@Test
public void visitOuterVar(){
    final int num = 2;
    Function<Integer,Integer> fun = (from) -> from * num;
    System.out.println(fun.apply(3));
}

}</pre>

提升HashMaps的性能

當hash沖突時,以前都是用鏈表存儲,在java8里頭,當節點個數>=TREEIFY_THRESHOLD - 1時,HashMap將采用紅黑樹存儲,這樣最壞的情況下即所有的key都Hash沖突,采用鏈表的話查找時間為O(n),而采用紅黑樹為O(logn)。

Date-Time Package

Java 8新增了LocalDate和LocalTime接口,一方面把月份和星期都改成了enum防止出錯,另一方面把LocalDate和LocalTime變成不可變類型,這樣就線程安全了。

@Test
    public void today(){
        LocalDate today = LocalDate.now();
        System.out.println(today);
    }

@Test
public void parseString(){
    // 嚴格按照ISO yyyy-MM-dd驗證,02寫成2都不行,當然也有一個重載方法允許自己定義格式
    LocalDate date = LocalDate.parse("2016-02-05");
    System.out.println(date);
}

@Test
public void calculate(){
    LocalDate today = LocalDate.now();
    LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
    System.out.println(firstDayOfThisMonth);

    // 取本月第2天:
    LocalDate secondDayOfThisMonth = today.withDayOfMonth(2);
    System.out.println(secondDayOfThisMonth);

    // 取本月最后一天,再也不用計算是28,29,30還是31:
    LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
    System.out.println(lastDayOfThisMonth);

    // 取下一天:
    LocalDate nextDay = lastDayOfThisMonth.plusDays(1);
    System.out.println(nextDay);

    // 取2015年1月第一個周一,這個計算用Calendar要死掉很多腦細胞:
    LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
    System.out.println(firstMondayOf2015);
}

@Test
public void getTime(){
    LocalTime now = LocalTime.now();
    System.out.println(now);
}

@Test
public void getTimeWithoutMillis(){
    LocalTime now = LocalTime.now().withNano(0);
    System.out.println(now);
}

@Test
public void parseTime(){
    LocalTime zero = LocalTime.of(0, 0, 0); // 00:00:00
    System.out.println(zero);

    LocalTime mid = LocalTime.parse("12:00:00"); // 12:00:00
    System.out.println(mid);
}</pre> 

java.lang and java.util Packages

比如數組的并行排序

public class UtilDemo {

int[] data = {4,12,1,3,5,7,9};

@Test
public void parallelSort(){
    Arrays.parallelSort(data);
    System.out.println(Arrays.toString(data));
}

@Test
public void testCollectPrallel() {
    //[4, 16, 17, 20, 25, 32, 41]
    Arrays.parallelPrefix(data, Integer::sum);
    System.out.println(Arrays.toString(data));
}

}</pre>

比如文件遍歷

 @Test
    public void list() throws IOException {
        Files.list(Paths.get(".")).filter(Files::isDirectory).forEach(System.out::println);
    }

@Test
public void walk() throws IOException {
    Files.walk(Paths.get("."), FileVisitOption.FOLLOW_LINKS).forEach(System.out::println);
}</pre> 

Concurrency

  • StampedLock

public class BankAccountWithStampedLock {

private final StampedLock lock = new StampedLock();
private double balance;

public void deposit(double amount) {
    long stamp = lock.writeLock();
    try {
        balance = balance + amount;
    } finally {
        lock.unlockWrite(stamp);
    }
}

public double getBalance() {
    long stamp = lock.readLock();
    try {
        return balance;
    } finally {
        lock.unlockRead(stamp);
    }
}

}</pre>

測試

@Test
    public void bench() throws InterruptedException {
        BankAccountWithStampedLock account = new BankAccountWithStampedLock();
        ExecutorService pool = Executors.newCachedThreadPool();
        List<Callable<Double>> callables = IntStream.range(1,5)
                .mapToObj(x -> (Callable<Double>) () -> {
//                    if (x % 2 == 0) {
//                        return account.getBalance();
//                    } else {
//                        account.deposit(x);
//                        return 0d;
//                    }
                    account.deposit(x);
                    return 0d;
                })
                .collect(Collectors.toList());
        pool.invokeAll(callables).forEach(x -> {
            try {
                System.out.println(x.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
        pool.shutdown();
        System.out.println(account.getBalance());
    }
 本文由用戶 MaximoGCU 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!