Java8实战[1-4]章要义笔记

注:《Java8 实战》一到四章的讲解偏重理论、需要慢慢从书中阅读理解、这里文章主要是以实用手记为目的,所以就简记一下Java8 实战的几个要义。

1、理解Lambda表达式

Java 8中解决这个问题的新工具——Lambda表达式。它可以让你很简洁地表示一个行为或传递代码。现在你可以把Lambda 表达式看作匿名功能,它基本上就是没有声明名称的方法,但和匿名类一样,它也可以作为参数传递给一个方法。

展示如何构建Lambda,它的使用场合,以及如何利用它使代码更简洁。我们还会介绍一些新的东西,如类型推断和Java 8 API中重要的新接口。最后,我们将介绍方法引用(method、reference),这是一个常常和Lambda表达式联用的有用的新功能。

使代码不在十分啰嗦,提高程序员在实践中使用行为参数化的积极性。

/**
 * @author chuan
 * @version 1.0
 * @description: Lambda表达式使用
 */
@RestController
@RequestMapping("/test")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {

    /**
     * Lambda表达式使用
     */
    @GetMapping("/printlnTest")
    public void printlnTest(){
        List<String> strings = Arrays.asList("A", "B", "C");
        // 打印结果 A、B、C
        strings.forEach(System.out::println);

        List<String> values = strings.stream().filter(s -> s.equals("B")).collect(Collectors.toList());
        // 打印结果 B
        values.forEach(System.out::println);
    }

}

2、Java 8在java.util.stream中添加了一个Stream API

Java 8在java.util.stream中添加了一个Stream API;

Stream<T>就是一系列T类型的项目。你现在可以把它看成一种比较花哨的迭代器。

Stream API的很多方法可以链接起来形成一个复杂的流水线,就像先前例子里面链接起来的Unix命令一样。推动这种做法的关键在于,现在你可以在一个更高的抽象层次上写Java 8程序了:思路变成了把这样的流变成那样的流(就像写数据库查询语句时的那种思路),而不是一次只处理一个项目。另一个好处是,Java 8可以透明地把输入的不相关部分拿到几个CPU内核上去分别执行你的Stream操作流水线——这是几乎免费的并行,用不着去费劲搞Thread了。

3、用行为参数化把代码传递给方法

Java 8中增加的另一个编程概念是通过API来传递代码的能力。这听起来实在太抽象了。

在 Unix的例子里,你可能想告诉sort命令使用自定义排序。虽然sort命令支持通过命令行参数来 执行各种预定义类型的排序,比如倒序,但这毕竟是有限的。 比方说,你有一堆发票代码,格式类似于2013UK0001、2014US0002……前四位数代表年份, 接下来两个字母代表国家,最后四位是客户的代码。

你可能想按照年份、客户代码,甚至国家来 对发票进行排序。你真正想要的是,能够给sort命令一个参数让用户定义顺序:给sort命令传 递一段独立代码。那么,直接套在Java上,你是要让sort方法利用自定义的顺序进行比较。

你可以写一个compareUsingCustomerId来比较两张发票的代码,但是在Java 8之前,你没法把这个方法传给另一个方法。你可以像本章开头时介绍的那样,创建一个Comparator对象,将之传递给sort方法,但这不但啰嗦,而且让“重复使用现有行为”的思想变得不那么清楚了。

Java 8增加了把方法(你的代码)作为参数传递给另一个方法的能力。描绘了这种思路。我们把这一概念称为行为参数化。它的重要之处在哪儿呢?

Stream API就是构建在通过传递代码使操作行为实现参数化的思想上的,当把compareUsingCustomerId传进去,你就把sort的行为参数化了。

    public void demo(){

        List<String> collect = list.stream()
                // 条件过滤
                .filter(user -> user.getUId() > 10)
                // 正序排序
                .sorted(Comparator.comparing(User::getUId))
                // 取出名字
                .map(User::getName)
                // 取出前两条
                .limit(2)
                // 去重
                .distinct()
                // 转出集合
                .collect(toList());
    }

4、Java 8的流实现并行比Java现有的线程API更容易

Java 8的流实现并行比Java现有的线程API更容易,因此,尽管可以使用synchronized来打破“不能有共享的可变数据”这一规则,但这相当于是在和整个体系作对,因为它使所有围绕这一规则做出的优化都失去意义了。在多个处理器内核之间使用synchronized,其代价往往比你预期的要大得多,因为同步迫使代码按照顺序执行,而这与并行处理的宗旨相悖。


这两个要点(没有共享的可变数据,将方法和函数即代码传递给其他方法的能力)是我们平常所说的函数式编程范式的基石,我们在第13章和第14章会详细讨论。与此相反,在命令式编程范式中,你写的程序则是一系列改变状态的指令。“不能有共享的可变数据”的要求意味着,一个方法是可以通过它将参数值转换为结果的方式完全描述的;换句话说,它的行为就像一个数学函数,没有可见的副作用。

    public void demo(){
        /**
         * 为了利用多核架构并行执行这段代码,你只需要把stream()换成parallelStream()
         * List<String> collect = userAges.parallelStream()
         */
        List<String> collect = list.parallelStream()
                // 条件过滤
                .filter(user -> user.getUId() > 10)
                // 正序排序
                .sorted(Comparator.comparing(User::getUId))
                // 取出名字
                .map(User::getName)
                // 取出前两条
                .limit(2)
                // 去重
                .distinct()
                // 转出集合
                .collect(toList());
    }

5、小结

总结下来可能就是这么一句话:语言需要不断改进以跟进硬件的更新或满足程序员的期待(如果你还不够信服,想想COBOL还一度是商业上最重要的语言之一呢)。

要坚持下去,Java必须通过增加新功能来改进,而且只有新功能被人使用,变化才有意义。所以,使用Java 8,你就是在保护你作为Java程序员的职业生涯。除此之外,我们有一种感觉——你一定会喜欢Java 8的新功能。随便问问哪个用过Java 8的人,看看他们愿不愿意退回去。

还有,用生态系统打比方的话,新的Java 8的功能使得Java能够征服如今被其他语言占领的编程任务领地,所以Java 8程序员就更需要学习它了。

猜你喜欢

转载自blog.csdn.net/amosjob/article/details/126218634