Java8相关
阅读Java8实战后的一些笔记
- 1. 行为参数化22
- 2. lamba表达式
- 3. 构造函数引用
- 4. 使用流
- 5. 设计模式使用
- 6. 默认方法
- 7. Optional
- 8. CompletableFuture:组合式异步编程
- 9. 新的日期和时间API
1. 行为参数化
定义一个接口,对选择建模
>
> public interface ApplePredicate{
boolean test(Apple apple);
}**定义一个类
实现该接口** > public class AppleRedAndHeavyPredicate implements ApplePredicate{
public boolean test(Apple apple){
return “red”.equals(apple.getColor())
&& apple.getWeight() > 150;
}
}使用匿名内部类简化代码 >
ListredApples = filterApples(apples,new ApplePredicate(){ public boolean test(Apple a){ return “red”.equals(a.getColor()); } }); 使用Lamba表达式简化 >
ListredApples = filterApples(apples,a->“red”.equals(a.getColor())); 使用泛型,抽象化代码 >
public interface Predicate{
boolean test(T t);
} > public staticList filter(List list,Predicate p){ List result = new ArrayList<>(); for(T e:list){ if(p.test(e)){ result.add(e); } } return result; }
2. lamba表达式
- 函数式接口
函数式接口 | 函数描述 | 原始类型特化 |
---|---|---|
Predicate< T> | T->boolean | IntPredicate, LongPredicate, DoublePredicate |
Consumer< T> | T->void | IntConsumer, LongConsumer, DoubleConsumer |
Function< T,R> | T->R | IntFunction< R>, IntToDoubleFunction, IntToLongFunction, LongFunction< R>, LongToDoubleFunction, LongToIntFunction, DoubleFunction< R>, ToIntFunction< T>, ToDoubleFunction< T>, ToLongFunction< T> |
Supplier | ()->T | BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier |
UnaryOperator | T->T | IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator |
BinaryOperator | (T,T)->T | IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator |
BiPredicate< L,R> | (L,R)->boolean | |
BiConsumer< T,U> | (T,U)->void | ObjIntConsumer< T>, ObjLongConsumer< T>, ObjDoubleConsumer< T> |
BiFunction< T,U,R> | (T,U)->R | ToIntBiFunction< T,U>, ToLongBiFunction< T,U>, ToDoubleBiFunction< T,U> |
- Lambdas 及函数式接口的例子
使用案例 | Lambda的例子 | 对应的函数式接口 |
---|---|---|
布尔表达式 | (List< string>list)->list.isEmpty() | Predicate
|
创建对象 | ()->new Apple(10) | Supplier< apple> |
消费一个对象 | (Apple a)->System.out.println(a.getWeight()) | Consumer< apple> |
从一个对象中选择/提取 | (String s)->s.length() | Function< String,Integer>, ToIntFunction |
合并两个值 | (int a,int b)->a*b | IntBinaryOperator |
比较两个对象 | (Apple a1,Apple a2)-> a1.getWeight().compareTo(a2.getWeight()) | Comparator< apple>, BiFunction< Apple,Apple,Integer>, ToIntBiFunction< Apple,Apple> |
- Lambda及其等效的方法引用
Lambda 等效的引用方法 (Apple a) -> a.getWeight() Apple::getWeight ()->Thread.currentThread().dumpStack() Thread.currentThread()::dumpStack (str,i) -> str.substring(i) String::substring (String s)->System.out.println(s) System.out::println
3.构造函数引用
默认方法的构造函数引用 > Supplier
appleSupplier = Apple::new; Supplier appleSupplier = ()->new Apple(); Apple a = appleSupplier.get(); 1个参数的构造函数引用
如果函数签名类似于Apple(Integer weight)
> FunctionappleFunction = Apple::new;
FunctionappleFunction = (weight)->new Apple(weight);
Apple a = appleFunction.apply(10);2个参数的构造函数引用
如果函数签名类似于Apple(Integer weight,String color)
> BiFunctionappleBiFunction = Apple::new;
BiFunctionappleBiFunction = (weight,color)->new Apple (weight,color);
Apple a = appleFunction.apply(10.“red”);比较器复合 > Comparator
c = Comparator.comparing(Apple::getWeighjt); apples.sort((a,b)->a.getWeight().compareTo(b.getWeight())); 可有化成(idea会自动帮我们优化) apples.sort(Comparator.comparing(Apple::getWeight));
逆序 > Comparator
c = Comparator.comparing(Apple::getWeighjt) .reversed(); 比较链接 先按照重量排序,然后按照颜色排序 > Comparator
c = Comparator.comparing(Apple::getWeighjt) .reversed() .thenComparing(Apple::getColor); 谓词复合
谓词接口包含3个方法:negate,and,or > Predicate
redApple = (Apple a)->“red”.equals(a.getColor()); Predicate heaveyApple = a->a.getWeight()>150; Predicate notRedApple = redApple.negate(); Predicate redAndHeavyApple = redApple.and(heavyApple);
函数复合
谓词接口包含3个方法:negate,and,or > Function
f = (a)->a*2; Function g = (b)->b+2; f.andThen(g) == g(f(x)) f.compose(g) == f(g(x)) 用此种方法可以组合成流水线工作,最后得出结果
4. 使用流
- distinct()
返回不重复的元素 如果是对象去重,可使用map的特效去重 - limit(3)
截断流,只选择前3个 - skip(3)
跳过流,跳过前3个 - map() 映射
- flatMap() 流扁平化,将各个生成的流扁平化为单个流
例如存在
Lista = [“1”,“2”,“3”];
Listb = [“a”,“b”]; 如何生成[“1a”,“1b”,“2a”,“2b”,“3a”,“3b”]? > - A.
Stream> result = a.stream().map(i->b.stream(j->return (i+j)));
Streams1 = [“1a”,“1b”]转换成的流;
Streams2 = [“2a”,“2b”]转换成的流;
Streams3 = [“3a”,“3b”]转换成的流;
对result进行收集会得到[[“1a”,“1b”],[“2a”,“2b”],[“3a”,“3b”]]不符合预期
> B. Stream
result = a.stream().flatMap(i->b.stream(j->return (i+j)));
对result进行收集会得到[“1a”,“1b”,“2a”,“2b”,“3a”,“3b”]符合预期anyMatch()
流中是否存在一个元素能够匹配 返回一个boolean值allMatch()
流中是否所有元素都能够匹配 返回一个boolean值nonMatch()
流中是否所有元素都不能匹配 返回一个boolean值findAny()
流中只要找到一个匹配的元素就短路并返回一个Optional值,如果不关心顺序,请用findAny findFirst()
顺序流中只要找到一个匹配的元素就短路并返回一个Optional值,关心顺序时使用 isPresent()
Optional中包含值返回true,否则返回false ifPresent(Consumer
block)
会在值存在时执行消费操作代码块T orElse(T other)
会在值存在时返回值,否则返回默认值reduce() int sum = list.stream().reduce(0,(a,b)->(a+b));初始为0的元素求和
int sum = list.stream().reduce(0,Integer::sum);
int multi = list.stream().reduce(1,(a,b)->a*b);初始为1的元素求积
Optionalmulti = list.stream().reduce((a,b)->a*b);没有初始值的的元素求积将返回optional 数值范围 range(),rangeClosed()
IntStream.range(1,100) = [1,100}
IntStream.rangeClosed(1,100) = [1,100]用Iterate创建无限流 例如:Stream.iterate(0,n->n+2).limit(5)
用generate创建无限流 generate接受一个Supplier
提供新的值
例如:Stream.generate(Math::random).limit(5);3.1 流收集数据
总量 > Stream.of(“1”.“2”).count();
或者 Stream.of(“1”.“2”).collect(Collectors.counting());MAX 和MIN 最大的苹果: > Comparator
appleComparator = Comparator.comparingInt(Apple::getWeight); Optional maxWeightApple = apples.stream().collect(Collectors.maxBy(appleComparator)); 最小值用Collectors.minBy()
Int求和用Collectors.summarizingInt()
Double求和用Collectors.summarizingDouble()
Long求和用Collectors.summarizingLong()规约reduce()
> apples.stream().collect(Collectors.reducing(0,Apple::getWeight,Integer::sum));
apples.stream().coll ect(Collectors.reducing(0,Apple::getWeight,(i,j)->(i+j)));
这两条代码是等价的 0 <–初始值
Apple::getWeight <–转换函数
(i,j)->(i+j) <–BinaryOperator分组groupingBy()
多级分组
> apples.stream().collect(Collectors.groupingBy(Apple::getWeight, Collectors.groupingBy(Apple::getColor)));分区partitioningBy()
分区是分组的特殊情况,会返回Map>类型,true是以组,false是一组 Collectors类的静态方法
工厂方法 返回类型 用于 示例 toList List<T>
把流中所有项目收集到一个List List<Dish> dishes = menuStream. collect(toList());
toSet Set<T>
把流中所有项目收集到一个Set,删除重复项 Set<Dish> dishes = menuStream. collect (toSet());
toCollection Collection<T>
把流中所有项目收集到给定的供应源创建的集合 Collection<Dish> dishes = menuStream.collect (toCollection() ,ArrayList::new);
counting Long
计算流中元素的个数 long howManyDishes = menuStream.collect (counting());
summingInt Integer
对流中项目的一个整数属性求和 int totalCalories =menuStream.collect(summingInt (Dish::getCalories) );
averagingInt Double
计算流中项目Integer属性的平均值 double avgCalories =menuStream.collect(averagingInt(Dish::getCalories));
summarizingInt IntSummaryStatistics
收集美于流中項目Integer 属性的統竍値,例如最大、最小、总和与平均値 IntSummaryStatistics menuStatistics =menuStream.collect(summarizingInt(Dish::getCalories));
joining String
连接对流中毎个項目调用toString方法所生成的字符串 String shortMenu =menuStream.map(Dish::getName).collect (joining(", "));
maxBy Optional<T>
一个包裹了流中按照给定比较器选出的最大元素的Optional,或如果流为空则为optional.empty() Optional<Dish> fattest = menuStream.collect(maxBy(comparingInt(Dish::getCalories)));
minBy Optional<T>
一个包裹了流中按照给定比较器选出的最小元素的Optional,或如果流为空则为optional.empty() Optional<Dish> lightest = menuStream.collect(minBy(comparingInt(Dish::getCalories)));
reducing 归约操作产生的类型 从一个作为累加器的初始値幵始,利用BinaryOperator与流中的元素逐个结合,从而将流归约为单个值 int totalCalories =menuStream.collect(reducing(0,Dish::getCalories, Integer::sum));
collectingAndThen 转换函数的类型 包裹另一个收集器,对其结果应用转换函数 int howManyDishes =menuStream.collect(collectingAndThen(toList(), List::size));
groupingBy Map<K, List<T>>
根据项目的一个属性的值对流中的项目作问组,并将属性值作为结果Map的键 Map<Dish.Type,List<Dish>> dishesByType = menuStream.collect(groupingBy(Dish::getType));
mapping 是一个收集器,可以传入两个函数, 一个函数对流中的元素做变换,另一个则将变换的结果对象收集起来 ,目的是在累加之前对每个元素应用一个映射函数 Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =menu.stream().collect(groupingBy(Dish::getType, mapping(dish -> { if (dish.getCalories() <=400) return CaloricLevel.DIET;else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;else return CaloricLevel.FAT; },toSet() )));
partitioningBy Map<Boolean, List<T> >
相据对流由每个项目应田谓词的结里求对项目经行分区 Map<Boolean, List<Dish>> vegetarianDishes =menuStream. collect (partitioningBy (Dish::isVegetarian) ) ;
待办事项
4.3 并行数据处理与性能
prallelStream()
parallel()将顺序流变为并行流
sequential()将并行流变为顺序流
自动装箱拆箱会大大降低并行流性能,此时应使用IntStream等原始类型流来避免这种操作。
5. 设计模式使用
使用lambda重构设计模式使用
4.1策略模式
待办事项
6. 默认方法
6. Optional
optional方法
序号 | 方法 & 描述 |
---|---|
1 | static |
2 | boolean equals(Object obj) 判断其他对象是否等于 Optional。 |
3 | Optional |
4 | Optional flatMap(Function<? super T,Optional> mapper)如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
5 | T get() 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
6 | int hashCode() 返回存在值的哈希码,如果值不存在 返回 0。 |
7 | void ifPresent(Consumer<? super T> consumer) 如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
8 | boolean isPresent() 如果值存在则方法会返回true,否则返回 false。 |
9 | Optional map(Function<? super T,? extends U> mapper) 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
19 | static |
11 | static |
12 | T orElse(T other) 如果存在该值,返回值, 否则返回 other。 |
13 | T orElseGet(Supplier<? extends T> other) 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
14 | |
15 | String toString() 返回一个Optional的非空字符串,用来调试 |