New features of Java8

  java, java8

Java language feature series

Order

This article mainly talks about the new features of Java8, which is also an important version. It has made greater changes in syntax, supports lamda expressions, and affects generic support comparable to Java5.

Property list

  • Lamda expression (Heavy weight)
  • Stream operation for collection
  • Improve the performance of HashMaps
  • Date-Time Package
  • java.lang and java.util Packages
  • Concurrency

Lamda expression (Heavy weight)

Method reference

/**
 * 静态方法引用:ClassName::methodName
 * 实例上的实例方法引用:instanceReference::methodName
 * 超类上的实例方法引用:super::methodName
 * 类型上的实例方法引用:ClassName::methodName
 * 构造方法引用:Class::new
 * 数组构造方法引用:TypeName[]::new
 * Created by codecraft 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("codecraft","china");
        System.out.println(a);
    }
}

Stream operation for collection

/**
 * 主要接口
 * 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 codecraft 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));
    }
}

Improve the performance of HashMaps

In java8, when the number of nodes is > = treife _ threshold-1, HashMap will use red and black trees to store Hash conflicts. in the worst case, all keys will have hash conflicts. if linked lists are used, the search time will be O(n), while red and black trees will be O(logn).

Date-Time Package

Java 8 adds LocalDate and LocalTime interfaces. on the one hand, it changes the month and week to enum to prevent errors, and on the other hand, it changes LocalDate and LocalTime to immutable types, thus making threads safe.

@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);
    }

java.lang and java.util Packages

Such as parallel sorting of arrays

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));
    }
}

Such as file traversal

 @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);
    }

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);
        }
    }
}

test

@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());
    }
  • Stream support for ConcurrentHashMap

References