第一章:为什么要关心Java8

给苹果按照重量排序

        Collections.sort(lists, new Comparator() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return o1.getWeight().compareTo(o2.getWeight());
            }

Java8的写法

 lists.sort(Comparator.comparing(Apple::getWeight));

Java8对硬件的影响

Java8之前程序都是单线程的,如果想使用多线程那么需要自行处理并发,虽然很Java提供了线程池和并发集合,但使用Java8会更容易实现多线程

并行与共享的可变数据
写代码时不能访问共享的可变数据,这些函数成为纯函数或无状态函数或无副作用函数

Stream API

Java8新的API提供了Stream,它支持许多处理数据的并行操作,从而可以避免使用synchronized

向方法传递代码技巧(方法引用,lambda表达式)

Java8之前使用匿名内部类实现行为参数化,Java8之后使用行为参数化(通过API传递代码)不需要创建匿名内部类

函数式编程
将代码传递给方法的功能,还让我们能够使用一整套新技巧

函数式编程的基石
1,没有共享的可变数据
2,将方法和函数传递给其他方法的能力

Java中的函数

程序执行期间不能传递叫二等公民(方法,类),能传递叫一等公民,java8将函数在运行时传递把他编程一等公民

        //筛选一个目录中隐藏的文件
        File[] hiddenFiles1 = new File(".").listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isHidden();
            }
        });
        //java8 写法
        File[] hiddenFiles2 = new File(".").listFiles(File::isHidden);

方法引用
java8使用 方法引用:: 语法(即吧这个方法最为值)
使用File::isHidden就创建了一个方法引用

lambda-匿名函数
比如(int a) -> x+1

筛选出绿色并且重量大于150克的苹果

//筛选绿色苹果
    public static List filterGreenApples(List inventory){
        List result = new ArrayList<>();
        for (Apple apple:inventory){
            if ("green".equals(apple.getColor())){
                result.add(apple);
            }
        }
        return result;
    }

    //筛选重量超过150克苹果
    public static List filterHeavyApples(List inventory){
        List result = new ArrayList<>();
        for (Apple apple:inventory){
            if (apple.getWeight() > 150){
                result.add(apple);
            }
        }
        return result;
    }

第一版写两个方法
可以看出很多代码都是重复的,变动部分只有if判断我们可以将这部分抽取出来

  public static boolean isGreenApple(Apple apple){
        return "green".equals(apple.getColor());
    }
    
    public static boolean isHeavyApple(Apple apple){
        return apple.getWeight() > 150;
    }
    
    public interface Predicate{
        boolean test(T t);
    }
    
    static List filterApples(List inventory,Predicate p){
        List result = new ArrayList<>();
        for (Apple apple:inventory){
            if (p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    public static void main(String[] args){
        filterApples(lists,StreamTest::isGreenApple);
        filterApples(lists,StreamTest::isHeavyApple);
    }

第二版
我们需要把变化的部分抽取出来,然后使用函数引用将变化的部分传递到函数中,这样就可以防止代码重复

 filterApples(lists,(Apple apple) -> "green".equals(apple.getColor()));
 filterApples(lists,(Apple apple) -> apple.getWeight() > 150);
 filterApples(lists,(Apple apple) -> apple.getWeight() < 150 || "brown".equals(apple.getColor()));

第三版
java8中我们可以直接使用lambda表达式

        //从一个列表中筛选金额较高的交易,然后按货币分组
        Map> transactionByCurrencies = new HashMap<>();
        for (Transaction transaction:transactions){
            if (transaction.getPrice() > 1000){
                Currency currency = transaction.getCurrency();
                List transactionForCurrency = transactionByCurrencies.get(currency);
                if (transactionForCurrency == null){
                    transactionForCurrency = new ArrayList<>();
                    transactionByCurrencies.put(currency,transactionForCurrency);
                }
                transactionForCurrency.add(transaction);
            }
        }

之前的写法很难一眼看出这些代码是做什么的,因为有好几个嵌套的控制流指令,下面我们使用流来解决这个问题

 Map> transactionByCurrencies2 = 
                transactions.stream()
                        .filter((Transaction transaction) -> transaction.getPrice() > 1000)
                        .collect(Collectors.groupingBy(Transaction::getCurrency));

Java8的实现非常简洁。
我们使用集合要自己去做迭代,for-each这种迭代是外部迭代,相反,有了Stream API根本就不用操心循环的事情。数据处理完全是在库里内部进行的。这种思想叫内部迭代
并且流可以更好的利用多个处理器并行处理任务

Collection是为了存储和访问数据,而Stream是对数据描述进行计算
将苹果筛选问题转化成流
顺序处理苹果筛选为题

        List heavyApples = lists.stream()
                .filter((Apple apple) -> apple.getWeight() > 150)
                .collect(Collectors.toList());

并行处理苹果筛选问题

        List heavyApple = lists.parallelStream()
                .filter((Apple apple) -> apple.getWeight() > 150)
                .collect(Collectors.toList());

为保证并行,函数式编程中主要的意思是,把函数作为一等值,并且含有第二层意思,即在执行元素之间无互动

接口中默认方法

一般是库设计师使用

Optional

防止出现空指针异常

Java8的新特性

函数参数化
lambda表达式,匿名参数

默认方法
Optional
CompletableFuture

你可能感兴趣的:(第一章:为什么要关心Java8)