Jdk1.8新特性看这篇就够了

前言

Jdk1.8提出了很多新特性,比如增加新的语言(Lambda表达式)、Stream API,Optional类。jdk8增加的新特性,使得程序效率会更快,提升程序员的编程体验。

Lambda表达式

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码。使得写出更简洁、灵活的代码。
举例:(o1,o2)->Integer.compare(o1,o2),其中->:Lambda操作符或箭头操作符;->左边:Lambda形参列表(接口中抽象方法的形参列表);->右边:Lambda体(重写接口抽象方法的方法体)。使用情况介绍,主要分为6种语法格式:

  • 语法格式一:无参,无返回值
    @Test
    public  void  test(){

        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable ...");
            }
        };
        runnable.run();

        System.out.println("*************Lambda************");
        Runnable runnable1=()->{
            System.out.println("Runnable ...");
        };
        runnable1.run();
    }
  • 语法格式二:有一个参数,无返回值
 @Test
    public void  test2(){
        Consumer<String>consumer=new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("helo.xf");

        System.out.println("*************Lambda************");

        //由于泛型指明<String>,这里s不用指明类型,编译器会自动进行类型推断
        Consumer<String>consumer1=(s)->{
            System.out.println(s);
        };
        consumer1.accept("hello,xf");
    }
  • 语法格式三:需要有一个参数,参数的小括号可以省略
 @Test
    public void  test3(){
        Consumer<String>consumer=new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("helo.xf");

        System.out.println("*************Lambda************");

        //参数s不用带小括号
        Consumer<String>consumer1=s->{
            System.out.println(s);
        };
        consumer1.accept("hello,xf");
    }
  • 语法格式四:两个或两个以上参数,方法体有多条执行语句,并有返回值
    @Test
    public void test4(){
        Comparator<Integer>comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println("o1:"+o1);
                System.out.println("o2:"+o2);
                return o1.compareTo(o2);
            }
        };
        int compare = comparator.compare(12, 20);

        System.out.println(compare);

        System.out.println("*************Lambda************");

        Comparator<Integer>comparator1=(o1,o2)->{
            System.out.println("o1:"+o1);
            System.out.println("o2:"+o2);
            return o1.compareTo(o2);
        };

        int compare1 = comparator1.compare(20, 34);
        System.out.println(compare1);
    }
  • 语法格式五:Lambda体只有一条语句,return与大括号若有,都可以省略
@Test
    public void  test5(){

        Comparator<Integer>comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        int compare = comparator.compare(12, 20);

        System.out.println(compare);

        System.out.println("*************Lambda************");

        Comparator<Integer>comparator1=(o1,o2)-> o1.compareTo(o2);

        int compare1 = comparator1.compare(20, 34);
        System.out.println(compare1);

    }

Lambda总结得到:->左边:Lambda形参列表类型可以省略(类型推断),若形参只有一个,这对()也可以省略;->右边:Lambda体使用一对{}包住,若体内只有一条语句(也包括return语句),这对{}和return关键字都可以省略,并且{}省略了return关键字也必须省略。其实Lambda本质也是一个借口的实例,看=号右边就能明白了。

函数式接口

FunctionalInterface:若一个接口中只声明一个抽象方法,则此接口称为函数式借口,可以在接口上加上@FunctionalInterface注解,验证该接口为函数式接口。例如:


/**
 * 函数式接口
 *
 */
@FunctionalInterface
public interface Animal {
    String eat(String food);

}

//Lambda表达式实现函数式接口

        Animal catAnimal=(s)->{
            System.out.println(s);
            return  s;
        };
        String s = catAnimal.eat("fish");  //fish

而且函数式接口的实现可以用Lambda表达式

四大函数式接口

在java.util.function包下,为我们提供了常用的四大函数式接口:Predicate<T>Supplier<T>Function<T, R>Consumer<T>

  • Predicate<T>:
    断定型接口,参数类型为T,根据传入的参数是否满足某些约束并返回boolean值,包含方法: boolean test(T t)
  Predicate<Integer>predicate=(t->{
           if (t>10) {
               return true;
           }else {
               return false;
           }
       });
        boolean test = predicate.test(1);  //false
  • Supplier<T>:
    供给型接口,不接受任何参数,根据泛型T,返回T类型的对象,包含 T get()方法
  Supplier<Student>supplier=(()->{
           return  new Student(1,"xf",24);
   });
   Student student = supplier.get();
  • Consumer<T>:
    消费型接口,参数类型为T,对传入的参数进行操作,无返回值,包含void accept(T t)方法
    Consumer<String>consumer=((s)->{
            System.out.println("s:"+s);
        });

        consumer.accept("xfnihao");  //xfnihao
  • Function<T, R>:
    函数型接口,对参数类型为T的对象操作后返回R类型结果,包含 R apply(T t)方法
   Function<String, Boolean>function=((s)->{
         
            if (s.equals("xf")){
                return true;
            }else {
                return false;
            }
        });

        Boolean result = function.apply("nihao");  //false

Stream API

Jdk8重大改变一个是Lambda表达式,另一个就是Stream API。Stream API实现函数式编程,使得程序代码更简洁、高效。常用用于对集合数据的计算,包括排序、查找、过滤等。
Stream的操作三个步骤:
1.创建Stream
一个数据源(如:集合、数组),获取一个流
2.中间操作
对数据源的数据进行处理
3.终止操作(终端操作)
一旦执行终止操作,就执行中间操作,并产生结果。

  • 代码演示

    /**
     * 1.创建流
     */
    @Test
    public void test1() {

        //顺序流
        List<Student> listData = Student.getStudents();

        Stream<Student> studentStream = listData.stream();

        //并行流
        Stream<Student> parallelStream = listData.parallelStream();


        int[] array = new int[]{1, 2, 3, 4, 5};
        //数据
        IntStream stream = Arrays.stream(array);
    }
 @Test
    /**
     * 2.中间操作->筛选与切片:类似操作SQL,通过where或聚合函数来进行条件查询
     */
    public void test2() {
        //顺序流
        List<Student> listData = Student.getStudents();

        //过滤 filter
        Stream<Student> stream = listData.stream();

        stream.filter((s)->s.getId()>1).forEach(System.out::println);

        //限流 limit
        Stream<Student> stream1 = listData.stream();

        stream1.limit(3).forEach(System.out::println);


        //跳过 skip
        Stream<Student> stream2 = listData.stream();
        stream2.skip(3).forEach(student -> System.out.println(student));


        //去重 distinct,要重写hashCode和equals方法

        Stream<Student> stream3 = listData.stream();
        stream3.distinct().forEach(student -> System.out.println(student));



    }


    /**
     * 中间操作->映射:map(function f)接收一个函数作为参数,将元素转为其他形式或提取元素
     */
    @Test
    public void test3() {

        List<Student> list = Student.getStudents();

        //将学生姓名转为大写
        list.stream().map(student -> student.getName().toUpperCase()).forEach(s -> System.out.println(s));


    }

    /**
     * 中间操作->排序
     */
    @Test
    public void test4(){

        //自然排序: Stream<T> sorted();

        List<Integer> list = Arrays.asList(0, 12, -90, 23, 100, 56, 2);
        list.stream().sorted().forEach(i -> System.out.println(i) );



        //定制排序: Stream<T> sorted(Comparator<? super T> comparator);按学号从大到小排序
        List<Student> listData = Student.getStudents();
        listData.stream().sorted((s1,s2)->{
            return -s1.getId().compareTo(s2.getId());
        }).forEach(item-> System.out.println(item));
    }
 /**
     * 3.终止操作->匹配与查找
     */

    @Test
    public void  test5(){
        List<Integer> list = Arrays.asList(0, 12, -90, 23, 100, 56, 2);
        //findFirst:返回第一个元素
        Integer i = list.stream().sorted().findFirst().get();
        System.out.println(i);


        //findAny:返回任意元素
        Optional<Integer> any = list.parallelStream().findAny();
        System.out.println(any);

        //count:返回元素个数
        long count = list.stream().count();
        System.out.println(count);


        //max:返回最大的元素
        Optional<Integer> max = list.stream().max((s1, s2) -> {
            return s1.compareTo(s2);
        });
        System.out.println(max);
    }

    /**
     *
     * 终止操作->规约:reduce,将流中的元素反复结合起来,得到新值并返回
     */
    @Test
    public void test6(){

        List<Integer> list = Arrays.asList(0, 12, -90, 23, 100, 56, 2);

        //reduce(T identity, BinaryOperator<T> accumulator);
        //求数组总和
        Integer sum = list.stream().reduce(0, (a, b) -> {
            return Integer.sum(a, b);
        });
        System.out.println(sum);
    }

    /**
     * 终止操作->收集:collect(Collectors ...)将处理后的流转为其他集合形式(Set/Map/List)
     */
    @Test
    public  void  test7(){

        List<Student> students = Student.getStudents();
        //返回有序List
        List<Student> list = students.stream().filter(
                student -> student.getId() > 1)
                .collect(Collectors.toList());

        //无序Set
        Set<Student> set = students.stream().filter
                (student -> student.getId() > 1).collect(Collectors.toSet());

    }

练习

/**
 * @author xfnihao
 * 根据Stream流条件查询
 */
public class StreamDemo {
    public static void main(String[] args) {

        Student s1=new Student(1,"a",12);
        Student s2=new Student(2,"b",8);
        Student s3=new Student(3,"c",18);
        Student s4=new Student(4,"d",24);
        Student s5=new Student(5,"e",20);
        Student s6=new Student(6,"f",20);

        //id为偶数&age>18&名字大写&倒排序获取一个
        //select name from tb where id %2==0 and age>18   func(name)  order by  ..
        List<Student>list=Arrays.asList(s1,s2,s3,s4,s5,s6);
        list.stream().filter((s -> {
            return s.getId() % 2 == 0;
        })).filter((s -> {
            return s.getAge() > 18;
        })).map((student -> {
            return student.getName().toUpperCase();
        })).sorted((o1, o2) -> {
            return -o1.compareTo(o2);
        }).limit(1).forEach(System.out::println);
    }
}

这样,我们就学会并使用Stream API,简化了代码,使得编程更高效。要想更熟练这套API,需要大量的实践。

总结

Jdk8中的常用新特性主要是Lambda表达式和Stream API,目前只需掌握这两个就够了。简化代码的编写和提升集合操作的效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值