jdk1.8新特性

      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);
    }



}
  • 内置核心接口
  1.     consumer<T> 消费型接口:void accept(T t)
  2.     Supplier<T> 供给型接口:T get()
  3.     Function<T,R> 函数型接口:R apply(T t)
  4.     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");

});
posted @ 2019-06-16 14:55  兵哥无敌  阅读(1274)  评论(0编辑  收藏  举报