JDK8新特性Lambda表达式

1.Lambda表达式&函数式接口

1.1 什么是Lambda表达式?

Lambda表达式可以理解为一种匿名函数的代替,lambda允许将函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递,目的是简化代码的编写。

1.2 什么是函数式接口?

lambda表达式需要函数式接口的支持,所谓函数式接口是指只有一个抽象方法,另外JDK8也提供了一个注解,帮助我们编译时检查语法是否符合@FunctionInterface.

1.3 Lambda表达式使用案例

lambda表达式的基本语法:

函数式接口  变量名 = (参数1,参数2,..)->{
	//方法体
}

案例1:

public class Main {
    public static void main(String[] args) {
        //匿名内部类
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello,lambda");
            }
        };
        new Thread(runnable).start();

        //lambda表达式
        Runnable runnable2 = ()->{System.out.println("hello,lambda");};
        new Thread(runnable2).start();

        //当里面只有一条语句的时候,花括号也可以省略
        Runnable runnable3 = ()->System.out.println("hello,lambda");
        new Thread(runnable3).start();

        //再进一步省略
        new Thread(()->System.out.println("hello,lambda")).start();

    }
}

案例2:

 //传统的模式
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length() - o2.length();
            }
        };
        TreeSet<String> treeSet = new TreeSet<>(comparator);

        //lambda表达式1
        Comparator<String> comparator1 = (o1,o2)-> o1.length() - o2.length();
        TreeSet<String> treeSet1 = new TreeSet<>(comparator1);

        //lambda表达式2
        TreeSet<String> treeSet2 = new TreeSet<>((o1,o2)->o1.length() - o2.length());

1.3 Lambda表达式注意事项

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分
左侧:(参数1,参数2…)表示参数列表
右侧: { } 内部是方法体

1.形参列表的数据类型会自动推断,所以(o1,o2)不用写成(String o1,String o2).
2.如果形参列表为空,只需保留();
3.如果形参只有1个,()可以省略,只需要参数的名称即可;
4.如果执行语句只有1句,且无返回值,{ }可以省略。若有返回值,想省去{ },则必须同时省略return,且执行语句也保证只有一句。
5.lambda不会生成一个单独的内部类文件。
6.lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该局部变量会报错(与内部类的语法一样)。

2.流式编程-StreamAPI

2.1 什么是Stream?

Stream是Java8中处理数组、集合的抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤、和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。

一个Stream表面上与一个集合很类似,集合中保存的是数据,而流设置的是对数据的操作。

Stream的特点:

1.Stream自己不会存储元素。
2.Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
3.Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

2.2 快速体验StreamAPI的特点

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("2015aa");
        list.add("aaaaaaaa");

        long count = 0;
        for (String s:list) {
           if (s.length()>3){
               count++;
           }
        }
        System.out.println(count);

		//streamAPI的方式结合lambda表达式
		//链式编程
	    long count1 = list.stream().filter(s -> s.length() > 3).count();
        System.out.println(count1);
    }

2.3 使用StreamAPI的步骤

1.创建一个Stream。(创建)
2.在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。(中间操作)
3.使用一个终止操作来产生一个结果。该操作会强制他之前的延迟操作立即执行。在这之后,该Stream就不会再被使用了。(终止操作)

2.4 创建Stream的方式

上面已经演示了集合创建stream的方式,这里面再补充一种数组的方式
这里面再补充一种数组的方式

int array = new int[]{1,2,3};
IntStream stream = Arrays.stream(array);
long count2 = stream.filter(i -> i > 1).count();
System.out.println(count2);

2.5 Stream的中间操作

2.5.1 筛选和切片(filter,limit,skip(n),distinct)
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Employee {
        private String name;
        private int age;
        private int salary;

        public Employee(String name,int age,int salary){
            this.name = name;
            this.age = age;
            this.salary = salary;
        }

        public Employee(){

        }

        @Override
        public String toString() {
            return "Employee{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", salary=" + salary +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
             return true;//不严谨
        }

        @Override
        public int hashCode() {
            return 1;//不严谨
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public int getSalary() {
            return salary;
        }

        public void setSalary(int salary) {
            this.salary = salary;
        }

    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("zhangsan",20,8000));
        employees.add(new Employee("lisi",30,18000));
        employees.add(new Employee("wangwu",40,28000));
        employees.add(new Employee("wangwu",40,28000));

        //筛选年龄大于30岁的员工
        Stream<Employee> employeesStream = employees.stream().filter(e -> e.getAge() > 30);
        employeesStream.forEach(t->System.out.println(t.getName()));

        //获取第一个
        Stream<Employee> limitStream = employees.stream();

        //跳过前面的两个,输出后面的两个
        Stream<Employee> skipStream = employees.stream().skip(2);
        skipStream.forEach(System.out::println);

        System.out.println("---------------------------------------");
        //自动调用equals和hashcode,去重操作
        Stream<Employee> distinctStream = employees.stream().distinct();
        distinctStream.forEach(System.out::println);
    }
}

2.5.2 映射(map)

map接收Lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用每个元素上,并将其映射成一个新的元素。

  Stream<String>  stream = employees.stream().map(e->e.getName());
  stream.forEach(System.out::println);
  
  //小写转换为大写
  List<String> list = Arrays.asList("a","b","c");
  Stream<String>  upperCaseStream = list.stream().map(String::toUpperCase);
  upperCaseStream.forEach(System.out::println);
2.5.3 排序(sorted)
System.out.println("-----------按年龄自然排序-------------------------");
        Stream<Integer> sortStream = employees.stream().map(Employee::getAge).sorted();
        sortStream.forEach(System.out::println);

        System.out.println("-----------定制排序-------------------------");
        Stream<Employee> sortStream1 = employees.stream().sorted((x,y)->{
            if (x.getAge() == y.getAge()){
                return x.getName().compareTo(y.getName());
            }else{
                return x.getAge() - y.getAge();
            }
        });
        sortStream1.forEach(System.out::println);

2.6 终止操作

2.6.1 遍历操作

forEach

2.6.2 查找和匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配的元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回流中元素的总个数
max——返回流中最大值
min——返回流中最小值
 boolean b1 = employees.stream().allMatch(e->e.getAge() > 30);
        boolean b2 = employees.stream().anyMatch(e->e.getAge() > 30);
        Optional<Employee> max = employees.stream().max((x,y) -> x.getAge() - y.getAge());
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(max.get());

2.7 Stream的串行和并行

Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Strean则是在多个线程上同时执行。
串行:

 public static void main(String[] args) {
            
        //初始化数据
        int max = 1000000;
        List<String> values = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }
            
        //串行计算
        long start = System.currentTimeMillis();
        long count = values.stream().sorted().count();
        System.out.println(count);
        long end = System.currentTimeMillis();
        long millos = end-start;
        System.out.println(millos);
        }

并行:

//并行计算
        long start = System.currentTimeMillis();
        long count = values.parallelStream().sorted().count();
        System.out.println(count);
        long end = System.currentTimeMillis();
        long millos = end-start;
        System.out.println(millos);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值