A.泛型定义

在JAVA8中经常用泛型来表示各种元素。
在JAVA中它是一个偽泛型,因为JVM层字节码层没有泛型的概念,泛型的代码被编译成字节码后,对应的泛型操作就消失了,这叫擦除法。
使用泛型元素之前会对该元素的类型做一个检查,才能继续使用。只多了检查这一步,其他的没有变化都一样。
但需要注意的是,如果我们去获取泛型类型这种类型定义,通过反射的方式拿到Class对象上的一些具体的元数据,是能拿到一些泛型相关的信息的。
取巧用法:Java中泛型可以T extends 接口1&接口2&接口3

在其他很多语言中,泛型是个真正存在的类型,
例如:

  • List listUser;
  • List listAppUser;

JAVA中这两个list对象是完全没有关系的。
其他具体泛型的语言中,listUser可以派生出子类型listAppUser,或者认为listAppUser有父类型listUser。这些类型是有层次关系真实存在的。

B.Lambda

1.表达式

1-1.定义:

(parameters) -> expression
(parameters) -> {statements;}

1-2.种类举例:

// 1. 不需要参数,返回值为 5
() -> 5

  1. int m() { return 5;}

// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x

  1. int m(int x) { return 2 * x;}

// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y

  1. int m(int x,int y) { return x - y;}

// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y

  1. int m(int x,int y) { return x + y;}

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

  1. void m(String s) { System.out.print(s); }

1-3.Java7/Java8演化实例

原始接口:

  1. interface MyLambdaInterface {
  2. void doSomeShit(String s);
  3. }

Java7实现接口:

  1. class MyLambdaInterfaceImpl implements MyLambdaInterface{
  2. @Override
  3. void doSomeShit(String s) {
  4. System.out.println(s);
  5. }
  6. }

Java8实现接口(没啥用):

  1. class Main {
  2. public static void main() {
  3. MyLambdaInterface myLambda = (s) -> System.out.println(s);
  4. }
  5. }

Java7使用接口:

  1. class Main {
  2. public static void main() {
  3. MyLambdaInterface myLambda = new MyLambdaInterfaceImpl();
  4. enact(myLambda, "test");
  5. }
  6. public static void enact(MyLambdaInterface lamdaInterface, String s) {
  7. lamdaInterface.doSomeShit(s);
  8. }
  9. }

Java8使用接口(不需要有显示实现接口的壳MyLambdaInterfaceImpl):

  1. class Main {
  2. public static void main() {
  3. MyLambdaInterface myLambda = (s) -> System.out.println(s);
  4. enact(s -> System.out.println(s), "test");
  5. }
  6. public static void enact(MyLambdaInterface lamdaInterface, String s) {
  7. lamdaInterface.doSomeShit(s);
  8. }
  9. }

2.函数式

核心注解:

@FunctionalInterface

核心接口:

  • Predicate 有参数、条件判断
  • Function 有参数、有返回值
  • Consumer 无返回值
  • Supplier 无参数、有返回值

3.EXAMPLE

https://gitee.com/zhukova/geek-time-java-class2021/blob/master/java8/src/main/java/com/geektime/java8/LambdaDemo.java

C.Stream

1.定义

Stream(流)是一个来自数据源的元素队列并支持聚合操作
•元素:特定类型的对象,形成一个队列。 Java 中的 Stream 并不会存储元素,而是按需计算。
•数据源:流的来源。可以是集合,数组,I/O channel,产生器 generator 等。
•聚合操作:类似 SQL 语句一样的操作,比如 filter, map, reduce, find, match, sorted 等。

和以前的 Collection 操作不同, Stream 操作还有两个基础的特征:
•Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格(fluent style)。这样做可以对操作进行优化,比如延迟执行(laziness)和短路(short-circuiting)。
•内部迭代:以前对集合遍历都是通过 Iterator 或者 For-Each 的方式,显式的在集合外部进行迭代,这叫做外 部迭代。Stream 提供了内部迭代的方式,通过访问者模式(Visitor)实现。

2.操作方法

中间操作Fluent API:继续stream

1、选择与过滤

  • filter(Predicate p) 接收 Lambda , 从流中排除某些元素。
  • distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素。
  • limit(long maxSize) 截断流,使其元素不超过给定数量。
  • skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。

2、映射

  • map(Function f) 接收 Lambda , 将元素转换成其他形式或提取信息;接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
  • mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream。
  • mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
  • flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接 成一个流。

3、排序

  • sorted() 产生一个新流,其中按自然顺序排序
  • sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序

终止操作:返回

1.查找与匹配

  • allMatch——检查是否匹配所有元素
  • anyMatch——检查是否至少匹配一个元素
  • noneMatch——检查是否没有匹配的元素
  • findFirst——返回第一个元素
  • findAny——返回当前流中的任意元素
  • count——返回流中元素的总个数
  • max——返回流中最大值
  • min——返回流中最小值

2.归约

  • reduce, 需要初始值(类比 Map-Reduce)

3.收集

  • collect
  • toList List 把流中元素收集到 List
  • toSet Set 把流中元素收集到 Set
  • toCollection Collection 把流中元素收集到创建的集合 count 计算流中元素的个数

4.迭代 forEach

  • summaryStatistics 统计最大最小平均值

3.EXAMPLE

https://gitee.com/zhukova/geek-time-java-class2021/blob/master/java8/src/main/java/com/geektime/java8/StreamIntegerDemo.java

https://gitee.com/zhukova/geek-time-java-class2021/blob/master/java8/src/main/java/com/geektime/java8/StreamStringDemo.java

D.Lombok

巴厘岛旁边的一个小岛

1.常规注解

@Setter
@Getter
@Data // =Getter + Setter + RequiredArgsConstructor + ToString + EqualsAndHashCode
@XXXConstructor
@Builder
@ToString
@Slf4j // lombok.extern.slf4j.Slf4j
@Log // lombok.extern.java.Log

2.maven-pom依赖


org.projectlombok
lombok
1.18.12

3.EXAMPLE

E.Guava

1.定义

JDK基础上做增强的一个第三方工具类库。
这个库提供用于集合,缓存,支持原语,并发性,常见注解, 字符串处理,I/O 和验证的实用方法。
JDK8 里的一些新特性源于 Guava,比如Stream里的Optional。

2.maven-pom依赖


com.google.guava
guava
29.0-jre

3.内容

集合[Collections]

Guava 对 JDK 集合的扩展,这是 Guava 最成熟和为人所知的部分

  • 1 不可变集合:用不变的集合进行防御性编程和性能提升。
  • 2 新集合类型:multisets, multimaps, tables, bidirectional maps 等
  • 3 强大的集合工具类:提供 java.util.Collections 中没有的集合工具
  • 4 扩展工具类:让实现和扩展集合类变得更容易,比如创建 Collection 的装饰器,或实现迭代器

缓存[Caches]

本地缓存实现,支持多种缓存过期策略

并发[Concurrency]

ListenableFuture:完成后触发回调的 Future

字符串处理[Strings]

非常有用的字符串工具,包括分割、连接、填充等操作

事件总线[EventBus]

发布-订阅模式的组件通信,进程内模块间解耦

反射[Reflection]

Guava 的 Java 反射机制工具类

4.EXAMPLE

https://gitee.com/zhukova/geek-time-java-class2021/blob/master/java8/src/main/java/com/geektime/java8/GuavaDemo.java

https://gitee.com/zhukova/geek-time-java-class2021/blob/master/java8/src/main/java/com/geektime/java8/GuavaEventBusDemo.java