Java8入门
Java8
为啥要学习Java8呢?我个人观点是因为函数接口的抽象会让我们编程的效率得到大幅提升,同时出问题的概率大幅下降,Java8会让代码变得简洁易懂的多的多。
为了让代码可以在多核的CPU机器上高效的运行
本文所有demo暂时无法提供
下面是一个Java8改造的示例
传统开发
List<Person> personList = Arrays.asList(new Person(21,50),new Person(22,55),new Person(23,60));
Collections.sort(personList, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
});
Java8开发
personList.sort(Comparator.comparing(Person::getWeight));
Java 8 的第一个编程思想就是流处理,流式一系列数据项,一次只生成一项,程序可以从输入流中一个一个读取数据项,然后以同样的方式将数据项写入输出流。一个程序的输出流很可能就是另一个程序的输入流。
在 Java 8 之前我们可以实现一个接口然后被强制重写这个接口的方法,那么隐含着很多问题:如果动物类新增一个fly()方法,那么其实dog这个类是不需要fly这个方法的,但是如果不重写就会编译报错。因此在 Java 8 之后也设计了默认方法这一种方式巧妙的解决了这种问题。
行为参数化
Lambda可以理解为是一种简洁的匿名函数的表示方式:它没有名称,但它有参数列表,函数主体,返回类型,还可以有一个可以抛出的异常。
Lambda表达式鼓励采用行为参数化的风格。利用Lambda表达式我们可以自定义一个Comparator对象
示例
- (String s)-> s.length():从一个对象中抽取值,具有一个 String 类型的参数,返回一个 int 类型的值,Lambda 表达式没有 return 语句,已经隐含了 return
- (Flower f) -> f.getPrice() > 8:布尔表达式,具有一个 Flower 类型的参数,返回一个 boolean 类型的值
- (String s) -> {System.out.print(s);} :消费一个对象,具有一个 String 类型的参数,没有返回值(void)
- () -> new Flower(“red”,8):创建一个对象,没有传入参数,返回一个 int 类型的值(1)
函数式接口
函数式接口就是只定义一个抽象方法的接口,并使用@FunctionalInterface标记。
Predicate
这个接口中定义了一个test()的抽象方法,它接受泛型 T 对象,并返回一个 boolean。你如果需要 表示一个涉及类型 T 的布尔表达式时,就可以使用这个接口。
Predicate示例
Consumer
这个接口定义了一个accept()的抽象方法,它接受泛型 T 对象,没有返回(void)。你如果需要访问类型 T 的对象,并对其执行某些操作,就可以使用这个接口。
Consumer示例
Function
这个接口定义了一个apply()的抽象方法,它接受泛型 T 对象,并返回一个泛型 R 的对象。你如果需要定义一个Lambda,将输入对象的信息映射输出,就可以使用这个接口。
Function示例
Supplier
这个接口定义了一个get()的抽象方法,它没有传入参数,会返回一个泛型 T 的对象,如果你需要定义一个 Lambda,输出自定义的对象,就可以使用这个接口。
Supplier示例
函数式接口 | 描述 | 示例代码 |
---|---|---|
BiConsumer<T, U> | 代表了一个接受两个输入参数的操作,并且没有返回值。 | BiConsumer<String, Integer> biConsumer = (s, i) -> System.out.println(s + i); |
BiFunction<T, U, R> | 代表了一个接受两个输入参数的方法,并返回一个结果。 | BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b; |
BinaryOperator | 代表了一个作用于两个同类型操作数的操作,并且返回同类型的结果。 | BinaryOperator<Integer> add = (a, b) -> a + b; |
BiPredicate<T, U> | 代表了一个接受两个参数的布尔值方法,返回一个布尔值结果。 | BiPredicate<String, Integer> predicate = (s, i) -> s.length() > i; |
BooleanSupplier | 代表一个提供 boolean 值的供应方,无输入参数,返回一个 boolean 值。 | BooleanSupplier booleanSupplier = () -> true; |
Consumer | 代表接受一个输入参数并且无返回值的操作。 | Consumer<String> consumer = s -> System.out.println(s); |
DoubleBinaryOperator | 代表作用于两个 double 值的操作符,并返回一个 double 值的结果。 | DoubleBinaryOperator multiply = (a, b) -> a * b; |
DoubleConsumer | 代表一个接受 double 值参数的操作,并且不返回结果。 | DoubleConsumer doubleConsumer = d -> System.out.println(d); |
DoubleFunction | 代表接受一个 double 值参数的方法,并返回一个结果。 | DoubleFunction<String> doubleToString = d -> String.valueOf(d); |
DoublePredicate | 代表一个拥有 double 值参数的布尔值方法,返回一个布尔值。 | DoublePredicate isPositive = d -> d > 0; |
DoubleSupplier | 代表一个提供 double 值的供应方,无输入参数,返回一个 double 值。 | DoubleSupplier doubleSupplier = () -> 3.14; |
DoubleToIntFunction | 接受一个 double 类型输入,返回一个 int 类型结果。 | DoubleToIntFunction doubleToInt = d -> (int) d; |
DoubleToLongFunction | 接受一个 double 类型输入,返回一个 long 类型结果。 | DoubleToLongFunction doubleToLong = d -> (long) d; |
DoubleUnaryOperator | 接受一个参数同为类型 double,返回值类型也为 double。 | DoubleUnaryOperator square = d -> d * d; |
Function<T, R> | 接受一个输入参数,返回一个结果。 | Function<String, Integer> stringLength = s -> s.length(); |
IntBinaryOperator | 接受两个参数同为类型 int,返回值类型也为 int。 | IntBinaryOperator add = (a, b) -> a + b; |
IntConsumer | 接受一个 int 类型的输入参数,无返回值。 | IntConsumer intConsumer = i -> System.out.println(i); |
IntFunction | 接受一个 int 类型输入参数,返回一个结果。 | IntFunction<String> intToString = i -> String.valueOf(i); |
IntPredicate | 接受一个 int 输入参数,返回一个布尔值结果。 | IntPredicate isEven = i -> i % 2 == 0; |
IntSupplier | 无参数,返回一个 int 类型结果。 | IntSupplier intSupplier = () -> 42; |
IntToDoubleFunction | 接受一个 int 类型输入,返回一个 double 类型结果。 | IntToDoubleFunction intToDouble = i -> (double) i; |
IntToLongFunction | 接受一个 int 类型输入,返回一个 long 类型结果。 | IntToLongFunction intToLong = i -> (long) i; |
IntUnaryOperator | 接受一个参数同为类型 int,返回值类型也为 int。 | IntUnaryOperator increment = i -> i + 1; |
LongBinaryOperator | 接受两个参数同为类型 long,返回值类型也为 long。 | LongBinaryOperator add = (a, b) -> a + b; |
LongConsumer | 接受一个 long 类型的输入参数,无返回值。 | LongConsumer longConsumer = l -> System.out.println(l); |
LongFunction | 接受一个 long 类型输入参数,返回一个结果。 | LongFunction<String> longToString = l -> String.valueOf(l); |
LongPredicate | 接受一个 long 输入参数,返回一个布尔值类型结果。 | LongPredicate isPositive = l -> l > 0; |
LongSupplier | 无参数,返回一个结果 long 类型的值。 | LongSupplier longSupplier = () -> 100L; |
LongToDoubleFunction | 接受一个 long 类型输入,返回一个 double 类型结果。 | LongToDoubleFunction longToDouble = l -> (double) l; |
LongToIntFunction | 接受一个 long 类型输入,返回一个 int 类型结果。 | LongToIntFunction longToInt = l -> (int) l; |
LongUnaryOperator | 接受一个参数同为类型 long,返回值类型也为 long。 | LongUnaryOperator doubleValue = l -> l * 2; |
ObjDoubleConsumer | 接受一个对象类型和一个 double 类型的输入参数,无返回值。 | ObjDoubleConsumer<String> objDoubleConsumer = (s, d) -> System.out.println(s + d); |
ObjIntConsumer | 接受一个对象类型和一个 int 类型的输入参数,无返回值。 | ObjIntConsumer<String> objIntConsumer = (s, i) -> System.out.println(s + i); |
ObjLongConsumer | 接受一个对象类型和一个 long 类型的输入参数,无返回值。 | ObjLongConsumer<String> objLongConsumer = (s, l) -> System.out.println(s + l); |
Predicate | 接受一个输入参数,返回一个布尔值结果。 | Predicate<String> predicate = s -> s.isEmpty(); |
Supplier | 无参数,返回一个结果。 | Supplier<String> stringSupplier = () -> "Hello"; |
ToDoubleBiFunction<T, U> | 接受两个输入参数,返回一个 double 类型结果。 | ToDoubleBiFunction<Integer, Integer> toDouble = (a, b) -> a + b; |
ToDoubleFunction | 接受一个输入参数,返回一个 double 类型结果。 | ToDoubleFunction<Integer> toDouble = i -> i * 2.0; |
ToIntBiFunction<T, U> | 接受两个输入参数,返回一个 int 类型结果。 | ToIntBiFunction<String, String> toInt = (s1, s2) -> s1.length() + s2.length(); |
ToIntFunction | 接受一个输入参数,返回一个 int 类型结果。 | ToIntFunction<String> toInt = s -> s.length(); |
ToLongBiFunction<T, U> | 接受两个输入参数,返回一个 long 类型结果。 | ToLongBiFunction<Integer, Integer> toLong = (a, b) -> a + b; |
ToLongFunction | 接受一个输入参数,返回一个 long 类型结果。 | ToLongFunction<Integer> toLong = i -> (long) i; |
UnaryOperator | 接受一个参数为类型 T,返回值类型也为 T。 | UnaryOperator<String> toUpperCase = s -> s.toUpperCase(); |
Lambda 表达式不仅能够使用主体里面的参数,也能够使用自由变量(在外层作用域中定义的变量)。
注意点:Lambda 表达式对于全局变量和静态变量可以没有限制的使用,但是对于局部变量必须显示声明为 final
因为实例变量是存储在堆中,而局部变量是存储在栈中,属于线程私有的。而 Lambda 是在一个线程中使用的,访问局部变量只是在访问这个变量的副本,而不是访问原始值。
构建方法引用
- 指向静态方法的方法引用(Integer的sum方法 == Integer::sum)
- 指向任意类型示例方法的方法引用(String的length方法 == String::length)
- 指向现有对象的示例方法的方法引用(flower实例的getPrice方法 == flower::getPrice)
比较器复合、谓词复合、函数复合
复合使用示例
流
基本概念
集合是 Java 中使用最多的API。流是 Java API 的新成员,它允许以声明式方式处理数据集合,可以看作是遍历数据集的高级迭代器。而且,流还可以透明地并行处理,这样就可以无需多写任何多线程代码了。
流操作demo
流可以说就是一个概念上固定的结构,通俗的说我觉得他就像一杯水,而这杯水呢我们只能喝一次或倒一次,但是我喝之前可以无限的操作他,比如我加了点糖又想去掉里面的杂质净化一下,最后我喝掉。
操作流也是一样的道理,当你遍历过一次某个流后他就不复存在了,你继续操作他就会报错了,只有在消费者要求的时候才会计算值
操作
获取流 -> 中间操作 -> 终端操作
List<String> colorList = flowerList.stream() //获取流
.filter(t->t.getPrice()<10) //中间操作
.limit(3) //中间操作
.map(Flower::getColor) //中间操作
.collect(Collectors.toList());//终端操作
流操作
操作 | 参数 | 描述 | 类型 |
---|---|---|---|
filter | Predicate<? super T> predicate | 返回一个新的流,只包含匹配给定谓词的元素。 | 中间操作 |
map | Function<? super T, ? extends R> mapper | 返回一个新的流,其元素是原流中的元素应用给定函数后的结果。 | 中间操作 |
mapToInt | ToIntFunction<? super T> mapper | 返回一个新的IntStream,其元素是原流中的元素应用给定函数后的结果。 | 中间操作 |
mapToLong | ToLongFunction<? super T> mapper | 返回一个新的LongStream,其元素是原流中的元素应用给定函数后的结果。 | 中间操作 |
mapToDouble | ToDoubleFunction<? super T> mapper | 返回一个新的DoubleStream,其元素是原流中的元素应用给定函数后的结果。 | 中间操作 |
flatMap | Function<? super T, ? extends Stream<? extends R>> mapper | 返回一个新的流,其元素是原流中的每个元素应用给定函数生成的流的所有元素。 | 中间操作 |
flatMapToInt | Function<? super T, ? extends IntStream> mapper | 返回一个新的IntStream,其元素是原流中的每个元素应用给定函数生成的流的所有元素。 | 中间操作 |
flatMapToLong | Function<? super T, ? extends LongStream> mapper | 返回一个新的LongStream,其元素是原流中的每个元素应用给定函数生成的流的所有元素。 | 中间操作 |
flatMapToDouble | Function<? super T, ? extends DoubleStream> mapper | 返回一个新的DoubleStream,其元素是原流中的每个元素应用给定函数生成的流的所有元素。 | 中间操作 |
distinct | 无 | 返回一个新的流,只包含不同的元素。 | 中间操作 |
sorted | 无 | 返回一个新的流,其元素根据自然顺序排序。 | 中间操作 |
sorted | Comparator<? super T> comparator | 返回一个新的流,其元素根据提供的比较器进行排序。 | 中间操作 |
peek | Consumer<? super T> action | 返回一个新的流,同步执行给定动作,它主要用来支持调试。 | 中间操作 |
limit | long maxSize | 返回一个新的流,截断后不超过给定长度。 | 中间操作 |
skip | long n | 返回一个新的流,丢弃前n个元素。 | 中间操作 |
forEach | Consumer<? super T> action | 对流中的每个元素执行给定操作。 | 终端操作 |
forEachOrdered | Consumer<? super T> action | 按照流的遇到顺序对每个元素执行给定操作。 | 终端操作 |
toArray | 无 | 返回包含流中所有元素的数组。 | 终端操作 |
toArray | IntFunction<A[]> generator | 返回一个包含流中所有元素的数组,使用提供的数组生成器。 | 终端操作 |
reduce | T identity, BinaryOperator accumulator | 将流中的元素归约为单个值,使用提供的初始值和累加函数。 | 终端操作 |
reduce | BinaryOperator accumulator | 将流中的元素归约为单个值,使用提供的累加函数。 | 终端操作 |
reduce | U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator combiner | 将流中的元素归约为单个值,使用提供的初始值、累加函数和组合函数。 | 终端操作 |
collect | Supplier supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner | 使用可变减少操作收集流中的元素。 | 终端操作 |
collect | Collector<? super T, A, R> collector | 使用Collector收集流中的元素。 | 终端操作 |
min | Comparator<? super T> comparator | 返回流中最小的元素。 | 终端操作 |
max | Comparator<? super T> comparator | 返回流中最大的元素。 | 终端操作 |
count | 无 | 返回流中的元素数量。 | 终端操作 |
anyMatch | Predicate<? super T> predicate | 返回流中是否有任何元素匹配给定谓词。 | 终端操作 |
allMatch | Predicate<? super T> predicate | 返回流中是否所有元素匹配给定谓词。 | 终端操作 |
noneMatch | Predicate<? super T> predicate | 返回流中没有元素匹配给定谓词。 | 终端操作 |
findFirst | 无 | 返回流中的第一个元素(如果有)。 | 终端操作 |
findAny | 无 | 返回流中的任意一个元素(如果有)。 | 终端操作 |
Collectors收集器
方法 | 参数 | 作用 |
---|---|---|
toCollection | Supplier<C> collectionFactory | 把元素收集到一个新的集合 (Collection) 中,集合由提供的工厂函数创建。 |
toList | 无 | 把元素收集到一个新的列表 (List) 中。 |
toSet | 无 | 把元素收集到一个新的集合 (Set) 中。 |
joining | 无 | 把元素连接成一个字符串。 |
joining | CharSequence delimiter | 用指定的分隔符连接元素。 |
joining | CharSequence delimiter, CharSequence prefix, CharSequence suffix | 用指定的分隔符、前缀和后缀连接元素。 |
mapping | Function<? super T, ? extends U> mapper, Collector<? super U, A, R> downstream | 将映射函数应用于每个输入元素后再进行收集。 |
collectingAndThen | Collector<T, A, R> downstream, Function<R, RR> finisher | 在使用下游收集器进行收集后,应用一个终结器函数。 |
counting | 无 | 计算元素的数量。 |
minBy | Comparator<? super T> comparator | 返回根据指定的比较器最小的元素。 |
maxBy | Comparator<? super T> comparator | 返回根据指定的比较器最大的元素。 |
summingInt | ToIntFunction<? super T> mapper | 计算整数属性的总和。 |
summingLong | ToLongFunction<? super T> mapper | 计算长整型属性的总和。 |
summingDouble | ToDoubleFunction<? super T> mapper | 计算双精度浮点数属性的总和。 |
averagingInt | ToIntFunction<? super T> mapper | 计算整数值的平均值。 |
averagingLong | ToLongFunction<? super T> mapper | 计算长整型值的平均值。 |
averagingDouble | ToDoubleFunction<? super T> mapper | 计算双精度浮点数值的平均值。 |
reducing | T identity, BinaryOperator<T> op | 根据指定的标识和二元运算符进行规约。 |
reducing | BinaryOperator<T> op | 根据信元运算符进行规约。 |
reducing | U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op | 在映射后根据标识和二元运算符进行规约。 |
groupingBy | Function<? super T, ? extends K> classifier | 根据分类器收集元素到一个Map中,Map的键是分类器的结果值,值是元素列表。 |
groupingBy | Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream | 根据分类器收集元素,然后对每个键的值进行下游收集。 |
groupingBy | Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream | 使用指定的Map工厂和下游收集器,根据分类器收集元素。 |
groupingByConcurrent | Function<? super T, ? extends K> classifier | 并行地根据分类器收集元素。 |
groupingByConcurrent | Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream | 并行地根据分类器收集元素,并对每个键使用下游收集器进行收集。 |
groupingByConcurrent | Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream | 使用指定的Map工厂和下游收集器,并行地根据分类器收集元素。 |
partitioningBy | Predicate<? super T> predicate | 根据谓词将元素部分到Map中,Map的键是布尔值,值是通过谓词的元素列表。 |
partitioningBy | Predicate<? super T> predicate, Collector<? super T, A, D> downstream | 根据谓词部分元素,并对每个部分的值进行下游收集。 |
toMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper | 将元素收集到Map中,键和值是通过映射函数计算的,如果键有重复会抛异常。 |
toMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction | 将元素收集到Map中,对重复键使用合并函数。 |
toMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier | 将元素收集到Map中,指定Map的工厂函数,对重复键使用合并函数。 |
toConcurrentMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper | 并行地将元素收集到ConcurrentMap中。 |
toConcurrentMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction | 并行地将元素收集到ConcurrentMap中,处理重复键。 |
toConcurrentMap | Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier | 并行地将元素收集到指定工厂函数生成的ConcurrentMap中,处理重复键。 |
summarizingInt | ToIntFunction<? super T> mapper | 收集整数值的摘要统计。 |
summarizingLong | ToLongFunction<? super T> mapper | 收集长整型值的摘要统计。 |
summarizingDouble | ToDoubleFunction<? super T> mapper | 收集双精度浮点数值的摘要统计。 |
流的构建
- 直接创建流
Stream<String> stream = Stream.of("hello","world");
Stream<String> emptyStream = Stream.empty();
- 由数组创建流
int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();
- 由文件生成流
long uniqueWords = 0;
try(Stream<String> lines =
Files.lines(Paths.get("data.txt"), Charset.defaultCharset())){
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct()
.count();
}catch(IOException e){
}
// 使用 Files.lines 得到一个流,其中的每个元素都是给定文件中的一行。然后,你可以对 line 调用 split 方法将行拆分成单词
Optional
开发中最经常遇到的异常某过于NullPointException了吧。因为这就是我们为了方便甚至不可避免的像 null 引用这样的构造所付出的代价。Java 8之后仿佛出现了转机,那就是用Optional来代替null。
方法 | 描述 | 用法示例 |
---|---|---|
Optional.ofNullable | 接受一个可能为 null 的值,如果值为 null ,返回一个空的 Optional 实例;如果值不为 null ,返回一个包含该值的 Optional 实例。 | Optional.ofNullable(person).map(Person::getName).orElse("没有数据啊"); |
Optional.of | 接受一个非 null 的值,如果值为 null ,会抛出 NullPointerException ;如果值不为 null ,返回一个包含该值的 Optional 实例。 | Optional.of(person).map(Person::getName).orElse("没有数据啊"); |
Optional.empty | 返回一个空的 Optional 实例,表示没有值。 | Optional.empty(); |
方法 | 描述 |
---|---|
filter(Predicate<? super T> predicate) | 如果值存在并且满足提供的谓词,返回包含该值的 Optional 对象;否则返回一个空的 Optional 对象。 |
get() | 如果值存在,将该值用 Optional 封装返回,否则抛出 NullPointerException 异常。 |
ifPresent(Consumer<? super T> action) | 如果值存在,执行使用该值的方法调用,否则什么也不做。 |
isPresent() | 如果值存在返回 true ,否则返回 false 。 |
map(Function<? super T, ? extends U> mapper) | 如果值存在,对该值执行提供的映射函数调用,返回映射后的值。 |
orElse(T other) | 如果有值则返回该值,否则返回指定的默认值。 |
orElseGet(Supplier<? extends T> other) | 如果有值则返回该值,否则返回由指定的 Supplier 接口生成的值。 |
orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果有值则返回该值,否则抛出由指定的 Supplier 接口生成的异常。 |