jdk1.8版本是2014发布的,自java 1.5以来最具有革命性的版本了,在语言、编译器、类库、开发工具以及Java虚拟机等方面都带来了不少新特性。
并且版本稳定,已经广泛应用于企业级开发。这些新特性能够帮助开发人员提升编码效率,加深对java的理解,因此作为一个合格的java程序员,掌握
和理解这些新特性是很有必要的。下面开始介绍这些新特性。
- lambda表达式
lambda表达式是将函数作为参数进行传递,从而实现了函数式编程(函数式编程在js中广泛应用),看下面一段传统方式创建线程的代码:
Runnable runnable1 = new Runnable() { @Override public void run() { System.out.println("runnable..."); System.out.println("run...."); }
利用lambda表达式可以这样写
Runnable runnable2 = ()->{ System.out.println("runnable..."); System.out.println("run...."); };
其中 () 代表参数, {}代表函数主体。表现为 (Type1 parameter1,Type2 parameter2........)->{statment1;statmenet2;......}
什么情况适用于lambda表达式呢?答案是 :能够接收Lambda表达式的参数类型,是一个只包含一个方法的接口,称为函数式接口,为此jdk1.8推出了一种标记注解@FunctionalInterface
@FunctionalInterface public interface Animal { String talk(String name); } //main Animal animal = (name)->"animal的name是:"+name; System.out.println(animal.talk("dog..."));
- 方法引用
Lambda方法体中的内容已经有实现,可以使用方法引用。前提是
1. Lambda体中的调用方法的参数,返回值要和该Lambda对应的函数式接口中抽象方法的参数和返回值一致
语法格式:
对象::实例方法名 Consumer<String> con = System.out:print
类::静态方法名 Comparator<Integer> com = Integer::compare;
类::实例方法名 BiPredicate<String,String> biPredicate = String::equals; == biPredicate = (x,y)->x.equals(y);
前提是参数列表中第一个参数是实例方法的调用者,第二个参数是实例方法的参数
或者第一个参数是实例方法的调用者,没有第二个参数 list.stream().map(String::toUpperCase).forEach(System.out::println); == list.stream().map(x->x.toUpperCase()).forEach(System.out::println);
若对参数有任何修改,则不能使用方法引用,而需键入完整地lambda表达式,如下所示:
list.forEach((String s) -> System.out.println("*" + s + "*"));
- 构造器引用
语法格式:类名::new
1.无参构造器
Supplier<Object> supplier = Object::new == Supplier<Object> supplier = ()->new Object()
2.一个参数的构造器
Function<String,String> fun = String::new == Function<String,String> fun = (p)-> new String(p)
import java.util.Arrays; import java.util.List; /** * Created by IntelliJ IDEA. * User: chenzhubing * Date: 2019/6/27 */ public class MyConsumer { public static void main(String[] args) { List<String> list = Arrays.asList("a","b","c"); list.forEach(x->MyConsumer.print(x)); list.forEach(MyConsumer::print); new MyConsumer().start(); } public void start(){ List<String> list = Arrays.asList("a1","b1","c1"); list.forEach(x->{new MyConsumer().print1(x);}); list.forEach(new MyConsumer()::print1); } public void print1(String str){ System.out.println(str); } public static void print(String str){ System.out.println(str); } }
- 内置核心接口
- consumer<T> 消费型接口:void accept(T t)
- Supplier<T> 供给型接口:T get()
- Function<T,R> 函数型接口:R apply(T t)
- R apply(T t)断言型接口:boolean test(T t)
Consumer:有参数,无返回值
/** * * @param param * @param con */ public void testConsumerInterface(Integer param, Consumer<Integer> con){ con.accept(param); } test.testConsumerInterface(10,(p)-> System.out.println(p));
Supplier:无入参,有返回值
/** * * @param supplier * @return */ public List<Integer> testSupplierInterface(Supplier<Integer>supplier){ List<Integer> list = new ArrayList<>(); list.add(supplier.get()); return list; } List result = test.testSupplierInterface(()->100); result.forEach(System.out::println);
Function:有入参,有出参
/** * * @param input * @param fun * @return */ public List<String> testFunctionInterface(Integer input,Function<Integer,String> fun){ List<String> list = new ArrayList<>(); list.add(fun.apply(input)); return list; } result = test.testFunctionInterface(100,p->p+"hello,world"); result.forEach(System.out::println);
Predicate : 有入参,返回值是boolean
/** * * @param input * @param predicate * @return */ public List<Integer> testPredicateInterface(Integer input, Predicate<Integer> predicate){ List<Integer> list = new ArrayList<>(); if(predicate.test(input)){ list.add(input); } return list; } result = test.testPredicateInterface(100,p->p>10); result.forEach(System.out::println);
- stream
jdk1.8新推出来的stream(和IO流没有关系)是针对Collection的增强。它专注于对集合对象进行各种非常便利、高效的聚合操作。配合lambda表达式能提升编码效率和程序的可读性。
1.Stream不会自己存储元素
2.Stream不会改变源对象,会返回一个新的Stream
3.Stream操作是延迟执行的,意味着需要结果的时候才执行
public class Person { private String name; private String nickName; private int gender; //0-男 1-女 private int salary; //薪水 public String getName() { return name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", nickName='" + nickName + '\'' + ", gender=" + gender + ", salary=" + salary + '}'; } public Person(){ } public static Person getPerson(){ return new Person(); } public Person(String name, String nickName, int gender, int salary) { this.name = name; this.nickName = nickName; this.gender = gender; this.salary = salary; } public void setName(String name) { this.name = name; } public int getGender() { return gender; } public void setGender(int gender) { this.gender = gender; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } } List<Person> list = new ArrayList<Person>(){ { add(new Person("张三","zhangsan",0,10)); add(new Person("李四","zhangsan",1,20)); add(new Person("王五","wangwu",0,30)); add(new Person("小刘","xiaoliu",1,40)); add(new Person("三木","sanmu",0,50)); } };
常用的操作有:filter,limit,skip,distinct,min,max,flatMap,sorted...........................
1)min :求集合中最小对象
Object obj = list.stream().min((p1,p2)->(p1.getSalary()-p2.getSalary())).get();
2 ) max : 求集合最大对象
Object obj = list.stream().max((p1,p2)->(p1.getSalary()-p2.getSalary())).get();
3 ) filter :根据条件过滤
list.stream().filter((p)->(1==p.getGender()))
4 ) limit: 取集合中的前多少个元素
list.stream().filter(
(p)->(1==p.getGender())
).limit(5)
5 ) sorted :排序
list.stream().sorted(
(p1,p2)->p1.getNickName().compareTo(p2.getNickName())
).forEach(
x-> System.out.println(x.getName())
)
6)allMatch
boolean r = list1.stream().allMatch(x->x.equals("a"));
System.out.println(r);
7)anyMatch
r = list1.stream().anyMatch(x->x.equals("e"));
System.out.println(r);
8)noneMatch
r = list1.stream().noneMatch((x)->x.equals("a"));
System.out.println(r);
9)count
long count = list1.stream().count();
System.out.println(count);
10 ) map: 归类,结果一般是一组数据
list1.stream().map(x->x.getSalary()).forEach(x-> System.out.println(x)); //将person中salary归类成一组数据
List<Integer> mapList = list1.stream().map(x->x.getSalary()).map(x->x-10).collect(Collectors.toList()); //将person中的salary归类成一组数据,并将salary-10
11 ) reduce: 归约 ,用来计算结果,结果是一个数值
Integer sum = list1.stream().map(x->x.getSalary()).reduce(0,(x,y)->x+y); //求总和,其中0是基准
int max = list1.stream().map(x->x.getSalary()).reduce(0,(x,y)->Integer.max(x,y));
12) collect : 收集,将处理后的结果输出到新的集合中,如list,set,map等 ;或者返回处理的结果,如求集合的个数,平均值等
list.stream().filter().collect(Collectors.toList())
list.stream().filter().collect(Collectors.toSet())
Long count = list1.stream().filter(p->p.getGender()==0).collect(Collectors.counting());
Double sumSalary = list1.stream().collect(Collectors.summingDouble(x->x.getSalary()));
double red = list2.stream().collect(Collectors.maxBy(Double::compareTo)).get();
double red = list2.stream().collect(Collectors.minBy(Double::compareTo)).get();
Map<Double,List<Double>> map = list2.stream().collect(Collectors.groupingBy(x->x)); //分组
Map<Double,Map<Double,List<Double>>> map1 = list2.stream().collect(Collectors.groupingBy(x->x,Collectors.groupingBy(x->x))); //多级分组
str = list1.stream().collect(Collectors.joining(",","start=","end=")); //结果集拼接
13 ) toMap
Map map = list1.stream().filter((p)->(1==p.getGender())).limit(2).collect(Collectors.toMap(Person::getName,Person::getNickName)); // key=name ,value=nickname
map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity())); //key=nickname, value = key对应的对象;注意key重复会抛出异常
map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity(),(oldValue,newValue)->newValue)); //key重复, 取新的key
map = list1.stream().collect(Collectors.toMap(x->x.getNickName(),Function.identity(),(oldValue,newValue)->oldValue)); //key重复, 取旧的key
- Optional
Optional的主要用处是可以有效的避免NullPointerException,配合lambda可以减少代码中大量的空指针判断,总之,代码更加优雅。
1) 创建Optional对象 :主要有两种方式
1.1 要求T非空,这种方式实际意义不大
Optional<T> op = Optional.of(T);
1.2 可以包装一个null的对象
Optional<T> op = optional.ofNullable(T);
2) ifPresent
op.ifPresent(p1->p1.setName("hello"));
如果T存在,则执行 p1->p1.setName("hello"),相当于
if(T != null){
p1.setName("hello");
}
3) orElse
如果T存在,返回;如果T不存在,则返回orElse里面的对象
op.orElse(Person.getPerson());
等价于
if(op.ifPresent()){
return op.get();
}else{
Person.getPerson();
}
4) orElseGet
如果T存在,返回;如果T不存在,则执行orElseGet里面的内容,并返回一个对象
op.orElseGet(()->{
System.out.println("helloworld");
System.out.println("sssssssssss");
return new Person();
});
5) orElseThrow
如果T存在,返回;如果T不存在,则执行orElseThrow里面的内容,并返回一个异常
op.orElseThrow(()->{
System.out.println("exception");
return new ArithmeticException("null");
});