第一章:为什么要关心Java8

给苹果按照重量排序

        Collections.sort(lists, new Comparator<Apple>() {
            @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<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple:inventory){
            if ("green".equals(apple.getColor())){
                result.add(apple);
            }
        }
        return result;
    }

    //筛选重量超过150克苹果
    public static List<Apple> filterHeavyApples(List<Apple> inventory){
        List<Apple> 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<T t>{
        boolean test(T t);
    }
    
    static List<Apple> filterApples(List<Apple> inventory,Predicate<Apple> p){
        List<Apple> 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<Currency,List<Transaction>> transactionByCurrencies = new HashMap<>();
        for (Transaction transaction:transactions){
            if (transaction.getPrice() > 1000){
                Currency currency = transaction.getCurrency();
                List<Transaction> transactionForCurrency = transactionByCurrencies.get(currency);
                if (transactionForCurrency == null){
                    transactionForCurrency = new ArrayList<>();
                    transactionByCurrencies.put(currency,transactionForCurrency);
                }
                transactionForCurrency.add(transaction);
            }
        }

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

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

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

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

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

并行处理苹果筛选问题

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

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

接口中默认方法

一般是库设计师使用

Optional<T>

防止出现空指针异常

Java8的新特性

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

默认方法
Optional
CompletableFuture

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Java8 in action 没有共享的可变数据,将方法和函数即代码传递给其他方法的能力就是我们平常所说的函数式...
    铁牛很铁阅读 1,344评论 1 2
  • 第一章 为什么要关心Java 8 使用Stream库来选择最佳低级执行机制可以避免使用Synchronized(同...
    谢随安阅读 1,549评论 0 4
  • 对于Java开发者来说,Java8的版本显然是一个具有里程碑意义的版本,蕴含了许多令人激动的新特性,如果能利用好这...
    jackcooper阅读 1,077评论 0 6
  • 人像卡(三张):补充句子,我这样做的时候是想说…… 注:这样做,是指你的一个行为,有一个行为是你真的受不了的,一直...
    兮兮AX阅读 212评论 0 0
  • 我相信总监说过的一句话:人只有想得简单才能跑得快.任何东西如果你一多想.你便散了.负重前行.必定累到自己.最终会导...
    AnSYoga抬头看见太阳花阅读 404评论 0 4

友情链接更多精彩内容