JAVA8 新增了很多特性,因为其简便、易懂,已经广泛用于生产环境中,为了不在工作的时候尴尬强烈建议掌握新特性。
主要有以下几点新特性:
1.Lambda表达式 2.函数式接口 3.方法引用 4.构造器引用 5.Stream API 6.Option类 7.DateTime API
本文主要对前5点进行介绍。
首先来看我们如果要构建一个Runnable接口的实现类会怎么做?很简单,构建一个匿名对象就可以了,匿名对象重写run方法一气呵成。
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
那要是想更简单的实现该怎么做呢?这就用到了Lambda表达式,先看示例。
Runnable runnable1=()->{System.out.println("hello");};
是不是有点过于简单了?初次一看,这是啥?为什么跟上面就一样了?下面来介绍一下Lambda表达式的语法:
(parameters) -> expression
或
(parameters) ->{ statements; }
()中填方法的参数,->为Lambda操作符,{}是方法体。
Lambda表达式仅可以作为函数式接口的实现类。
函数式接口:一个接口中仅包含一个方法,这样的接口就被称为函数式接口,比如Runnable接口中只有void run()方法。
现在大概懂了吧,上面的代码由Lambda表达式作为Runnable接口的实现类,所以和上面的代码是等价的。
注意Lambda表达式中的(){}以及参数类型在一定情况都是可以省略的,如参数只有一个时:
public interface Predicate<T> {
boolean test(T t);
}
Predicate<String>s= str->true;
使用Lambda表达式时,必须非常明确这个函数式接口中的参数和返回值,这样才能写的出来。
方法引用利用::操作符来指代方法,一般用于配合Lambda表达式使用。
首先看Compartor接口,仅有一个方法compare,符合函数式接口的定义,所以可以用Lambda表达式来替代接口实现类的实现
public interface Comparator<T> {
int compare(T o1, T o2);
}
Lambda实现:
Comparator<Integer>c2=(o1,o2)->o1-o2;
再看看Integer类中compare方法的参数:int compare(int,int),跟Comparator< Interger> 接口中的compare方法参数一样,所以可以用Integer::compare来替换Comparator接口中的compare方法,这就是方法引用。
Comparator<Integer>c=Integer::compare;
方法引用中存在一种特殊情况,接口方法中参数为n个,被引用的方法的类为接口方法的第一个参数,方法仅含有n-1个参数。这种情况也符合方法引用的条件,说起来很抽象,举个例子就懂了。
Compartor< String>中的compare方法: int compare(String o1, String o2);
String的CompareTo方法: public int compareTo(String anotherString);
Lambda表达式:
Comparator<String>c=String::compareTo;
compare接口方法有2个参数,其中第一个参数为String,而compareTo(String)只有1个参数并且compareTo方法为String类的方法,正好对应接口方法的第一个参数,这样也能实现方法引用。
用类名::new来替代返回值为对象的函数式接口。
先看Supplier接口,仅有一个get方法返回对象T。
public interface Supplier<T> {
T get();
}
如果用Lambda表示式的话:
class Employee{
int a ;
Employee(){}
Employee(int a){this.a =a;}
}
Supplier<Employee>supplier=()->new Employee();
Supplier<Employee>supplier= Employee::new;
构造器引用还会自动匹配有参构造,当接口函数签名: 对象 (构造器参数…)时会自动匹配
public interface Function<T, R> {
R apply(T t);
}
//Functon中存在方法:Employee apply(Integer)
Function<Integer,Employee>f =Employee::new;
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合数组运算和表达的高阶抽象。
Stream API 可以极大提高 Java 程序员的生产力,让程序员写出高效率、干净、简洁的代码。
stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
多说无益,实例演示:
先将ArrayList中加入了1、2、3共3个元素,再获取ArrayList中的流对象,通过流对象过滤得到集合中>1的元素,并将过滤结果返回成一个新的集合collect。
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
Stream<Integer> stream = integers.stream();
List<Integer> collect = stream.filter(i -> i > 1).collect(Collectors.toList());
对于Collection集合:
Collection.stream()
Collection.parallelStream()
对于数组:
Arrays.stream(T array) or Stream.of()
流的操作主要分为中间操作、终止操作,中间操作有map映射、filter过滤、limit限制输出等等,终止操作有foreach遍历、match是否匹配、collect收集等等。只有经过终止操作才会得到流的结果。
将流中的元素映射(转换)成另外的元素。比如下面将students集合转换成了String集合
List<Student>students;
List<String> studentNames = students.stream().map(Student::getName)
.collect(Collectors.toList());
filter过滤流中的元素,应当传入Predicate接口实现类 方法签名:boolean test(T t)
根据对象的hashCode去重
传入Comparator接口实现类排序,也可以不传参数,需要流中的对象实现Comparator接口
ArrayList<Integer> integers = new ArrayList<>();
...
Stream<Integer> stream = integers.stream();
stream.sorted(Integer::compare);
限制输出多少条结果
students.stream().limit(6).forEach(System.out::println);
跳过n个元素
遍历流,传入Consumer接口实现类void accept(T t)对流中元素进行操作,一般直接传入System.out::println打印所有元素。
stream.forEach(System.out::println);
可以将流转换成指定的数组,传入对象[]::new
Integer[] array = stream.toArray(Integer[]::new);
传入Comparator接口实现类返回最大值、最小值,以Optional对象的方式返回,可以通过Option.get()获取。
Optional<T> min(Comparator<? super T> comparator);
Optional<T> max(Comparator<? super T> comparator);
返回流中元素数量
凝结、归纳流中所有元素,它需要提供一个起始值,然后按一定规则进行运算,比如相加等,它接收一个二元操作 BinaryOperator函数式接口。
重载方法:T reduce(BinaryOperator accumulator); 初始值为0
计算集合中的所有元素之和:
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
System.out.println(integers.stream().reduce(0, (v1, v2) -> v1 + v2));
//等价于
System.out.println(integers.stream().reduce(Integer::sum));
boolean anyMatch(Predicate super T> predicate);
boolean allMatch(Predicate super T> predicate);
boolean noneMatch(Predicate super T> predicate)
顾名思义,any只要存在就返回true,all所有都符合条件返回true,none都不满足返回true。
一般用这个方法,还有个重载不常用。
将流中元素转换成集合
List<Integer> = integers.stream().collect(Collectors.toList());