JAVA8新特性
速度更快
Lambda表达式
Stream API
便于并行
最大化的减少空指针异常
速度更快
HashMap
Lambda表达式
简介
Lambda表达式,也可称为闭包,它允许把函数作为一个方法的参数,使用Lambda表达式可以使代码变的更加简洁紧凑。
语法格式
(parameters) ->{ statements; }
重要特征:
不需要声明参数类型,编译器可以自动类型推断
如果只有一个参数,()可以省略
如果主体部分只有一个语句,可以省略{}
如果主体只有一个表达式,可以省略return关键字
注意事项:
要用lambda形式使用接口,需要接口为函数式接口
lambda表达式只能引用标记了final的外层局部变量
这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
函数式接口:
简介:
所谓函数接口,是只有一个抽象方法的接口,但是允许其他使用default方法修饰的接口存在.
java8中提供了一个注解@FunctionalInterface,用来校验一个接口是不是函数式接口.
JAVA8的四大核心内置函数式接口:
1) Consumer:消费型接口,适用于有一个入参,没有返回值的场景.lambda表达式代表的是[[消费过程]]
public interface Consumer<T> {
void accept(T t);
}
2) Supplier:生产型接口,适用于没有入参,有一个返回值的场景.lambda表达式代表的是[[生产过程]]
public interface Supplier<T> {
T get();
}
3) Function:加工型接口,适用于一个类型的入参,一个类型的返回值场景.lambda表达式代表的是[[加工过程]]
public interface Function<T, R> {
R apply(T t);
}
4) Predicate:断言型接口,适用于用于条件判断的场景,lambda表达式代表的是[[条件]]
public interface Predicate<T>{
boolean test(T t);
}
构造器引用和方法引用
构造器和方法引用可以认为是Lambda的另一种表现形式:
1)构造器引用,它的语法是Class::new
Supplier<Student> s = () -> new Student()
Supplier<Student> s = Student::new;
s.get();
2)类的静态方法引用,它的语法是Class::static_method
Comparator<Integer> c = (x,y) -> Integer.compare(x,y);
Comparator<Integer> c = Integer::compare;
3)对象的实例方法引用,它的语法是instance::method
Consumer<String> c = (x) -> System.out.println(x);
Consumer<String> c = System.out::println;
c.accept("Yes");
4)类的实例方法引用,它的语法是Class::method
BiPredicate<String, String> bp = (x,y) -> x.equals(y);
BiPredicate<String, String> bp = String::equals;
bp.test("A", "B");
Stream API
Stream API极大简化了集合框架的处理,当使用Stream时,会有三个阶段:
1)创建一个Stream。
2)在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。
3)使用一个终止操作来产生一个结果。该操作会强制他之前的延迟操作立即执行。在这之后,该Stream就不会在被使用了。
1)Stream的创建:
通过Collection实例的stream()产生
Stream<String> stream = new ArrayList<String>().stream();
通过Arrays.stream()产生
Stream<Integer> stream = Arrays.stream(new Integer[10]);
通过Stream.of()产生
Stream<String> stream3 = Stream.of("10","20");
通过迭代器生成Stream.iterate()
Stream<Integer> stream4 = Stream.iterate(0,(x) -> x + 2);
通过生成器生成Stream.generate()
Stream<Double> stream5 = Stream.generate(() -> Math.random());
通过File.lines(path)获取
2)Stream对数据的中间操作:
(1)切片和筛选
filter(筛选):筛选符合条件的数据
limit(截取):截取指定数量的数据
skip(跳过):跳过指定数量的数据
distinct(去重):去掉重复的数据,根据对象的hashCode和equals结果比对两个对象
(2)映射
map-------接受Lambda,将元素转换成其它形式或者提取信息
flatMap---接受Lambda,将流中的每一个元素转换成其它形式或者提取信息
(3)排序
sorted(Comparator com):可以按照默认排序,也可以自定义排序方式
3)Stream的终止操作:
(1)匹配:
allMatch---是否全部匹配
anyMatch---是否至少匹配上一个
noneMatch--是否全不匹配
(2)查找:
findFirst--返回第一个元素
findAny----返回任意一个元素
count------返回元素个数
max--------返回元素最大值
min--------返回元素最小值
(3)规约:
reduce-----数据整合
P_OUT reduce(final P_OUT identity, final BinaryOperator<P_OUT> accumulator)
Optional<P_OUT> reduce(BinaryOperator<P_OUT> accumulator)
(4)收集:
collect(Collector c)---将流收集到指定的收集器中
java8中提供了一个Collectors的工具类用来产生Collector,常用方法有:
toList() 将流中的元素收集到List中
list.stream().collect(Collectors.toList())
toSet() 将流中的元素收集到Set中
list.stream().collect(Collectors.toSet())
toCollection() 将流中的元素收集到创建的集合中
list.stream().collect(Collectors.toCollection(ArrayList::new))
counting() 计算流中元素的个数
list.stream().collect(Collectors.counting())
summingDouble() summingInt() summingLong() 计算流中指定元素的和
list.stream().collect(Collectors.summingInt(Student::getAge))
averagingDouble() averagingInt() averagingLong() 计算流中指定元素的平均值
list.stream().collect(Collectors.averagingDouble(Student::getAge))
summarizingInt() summarizingLong 返回流中的统计信息
list.stream().collect(Collectors.summarizingInt(Student::getAge))
collectingAndThen() 连接处理,在一个处理之后再进行一个处理
list.stream().collect(Collectors.collectingAndThen(Collectors.summarizingInt(Dish::getCalories),a->a.getMax()))
join() 使用指定字符连接流中的每一个元素
list.stream().collect(Collectors.joining(",","--","--"))
groupingBy() 对流中元素根据某一属性进行分组[可以统计出每组的数量]
list.stream().collect(Collectors.groupingBy(Student::getAge))
partitioningBy() 对流中的数据根据true或false进行分区
list.stream().collect(Collectors.partitioningBy(Student::getAge))
并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。
Stream API可以声明性地通过parallel()与sequential() 在并行流与顺序流之间进行切换。
Optional
Optional是一个容器类,代表一个值存在或不存在.常用方法:
Optional.of(T t): 创建一个Optional实例
Optional.empty(): 创建一个空的Optional实例
Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例
isPresent(): 判断是否包含值
ifPresent(Consumer c): 判断是否包含值,如果有值,执行此操作
orElse(T t): 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
接口的默认方法和静态方法
Java 8使用两个新概念扩展了接口的含义:默认方法和静态方法。
默认方法:
默认方法使用default修饰,实现此接口的类不在强制实现默认的方法
如果一个类继承了一个父类的同时又实现了一个接口,并且类中和接口中存在重名的方法,则采用类优先原则
如果一个类同时实现了两个带有重名default方法的接口,则要求显示实现此方法
接口提供的默认方法可以被接口的实现类继承或者覆写.
静态方法:
静态方法采用static修饰