1、概念
lambda表达式是特殊的匿名内部类,语法更简洁。
lambda表达式允许报函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。
2、语法
<函数式接口> <变量名> = (参数1,参数2…) -> {()
//方法体
};
函数式接口:函数式接口就是一个接口里面,只拥有一个抽象函数,这样的接口被称为函数式接口。
为什么只能是一个函数呢?
因为在lembda表达式中,它在对方法进行重写的时候是没有函数名的,所以这个因数就限制了函数个数。语法简洁便有限制。
例如:
public class Lambda {
public static void main(String[] args) {
//使用lembda表达式写一个线程,实现接口Runnable的线程。
Runnable r=()->{
for(int i=0;i<10;i++) {
System.out.println(i);
}
};
//启动线程
new Thread(r,"线程1").start();
}
}
//其实就是一个匿名内部类的简写
3、常见的函数式接口
他们的用法如说明一样,消费型接口自己一般使用在传一个值给方法,然后在控制台上显示,就比如猫的吃方法,传一种食物给函数,然后显示猫吃什么。
供给型接口,主要用在不给参数能到的一个值,比如数学中的随机数方法,调用便能得到一个数。
函数型接口,简单的一传一返回,传值给函数,然后要得到一个值
断言型接口,传入一个值,得到一个Boolean值。
4、方法引用
lambda表达式的一种更简单的写法
大概用法为,一个函数式接口要重写方法,刚好在别的地方有类似的方法(与我要重写的方法体差不多,并且参数与返回值一样),这时我们就不用再重写方法体,就直接引用这个函数作为重写的方法体。
常见的引用形式:
对象::实例方法
类::静态方法
类::实例方法
类::new
这个引用这一块挺有趣的,基本使用如下,因为是做笔记,所以方法都需要刻意写,如果在实际应用中,可能就会一时想不到这个引用方法。
首先类::静态方法
//第三节中有四个常用方法,那么就使用一个处于中间位置的函数型接口。
//已知函数型接口是一个一传递一返回的接口,想要使用(类::静态方法)引用方法实现该接口就需要一个静态函数,并且该静态函数有一个参数,且有一个返回值
//创建一个类,类里面写个静态方法,该静态方法有一个参数,且有返回值
public class Leijingtai {
//写一个方法,传入一个整数,把这个整数的值加10然后返回出去
public static int add(int a) {
return a+10;
}
}
//接下来是引用
import java.util.function.Function;
public class Yinyong {
public static void main(String[] args) {
Function<Integer, Integer> fun=Leijingtai::add;
//function<>便是前面所提到的函数式接口,该接口第一个泛型是参数的数据类型,第二个泛型是返回值的数据类型。
//泛型里面只能写引用类型,所以写了两个int的包装类Integer
//apply是function这个函数型接口的一个抽象方法(function接口里面也只有这一个抽象方法),所以我们实际上重写的就是apply方法。所以调用的写法就是: 类对象.apply(20) fun.apply(20)
System.out.println(fun.apply(20));
}
}
5、stream
5.1概念
流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作。
自己理解:流就相当于工厂里的机器,不同的机器有不同的功能,就相当于不同的操作,这些机器的操作就是对数据的处理,这些数据从流开始的地方进入,操作完之后离开流。流里面是不存放数据的,就象加工机器不是用来存储产品一样。
5.2Stream特点
Stream 自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream,(假如我有一个文件,我是用流对他进行处理,那么流会在这个文件上拷贝一个副本文件然后对副本文件进行处理,源文件的内容依旧没有改变,但是我们可以接收到进过改变的副本文件)
Stream 操作是延迟执行的,会等到需要结果的时候才执行。(就是需要特定的操作使它执行,而进过这些操作之后就必定到了数据流出的地方,如果还要对数据进行处理就要重新调用流)
5.3 Stream使用步骤
创建:
新建一个流。
中间操作:
在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。
终止操作:
使用一个终止操作来产生一个结果。该操作会强制之前的延迟操作立即执行,在此之后,该
Stream就不能使用了。
创建Stream的方法有:
- 通过Collection对象的stream()或parallelStream()方法。
- 通过Arrays类的stream()方法。
- 通过Stream接口的of()、iterate()、generate()方法。
- 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。
中间操作
fiter 过滤,通过过滤可以筛选出自己要的元素,筛选方案要自己写
limit 限制,可以限制流的个数,本来有五个,可以把它变成前两个,从第一个开始保留多少个的意思
skip 跳过,跳过前面多少个然后对后面的数据进行操作。
distinct 去重复,可以用于去掉重复的元素
sorted 排序,排序规则要自己写。
map 获取一种属性的值,比如操作的数据是几个学生对象,然后可以通过map把所有学生对象的名字取出来单独操作。
parallel 采用多线程,效率会快一点
终止操作
forEach 循环(和增强for一个类型),流一般操作的是一个数组,或者一个集合,通过该方法可以把一个个的元素输出
min 获得最小值
max 获得最大值
count 获取元素个数
reduce 计算吧
collect 收集,想要得到操作过的元素,那么就靠这个方法收集。
一些流操作的实例如下
import java.util.ArrayList;
import java.util.List;
public class Liu {
public static void main(String[] args) {
//创建一个学生集合
List<Student> list=new ArrayList<Student>();
list.add(new Student("张三","男",78,"1234"));
list.add(new Student("李四","男",56,"1236"));
list.add(new Student("王五","女",67,"1235"));
list.add(new Student("赵六","男",89,"1237"));
list.add(new Student("陈七","女",45,"1238"));
//使用流对集合进行排序输出,排序依据学号
list.stream().sorted((e1,e2)->e1.getNum().compareTo(e2.getNum())).forEach(System.out::println);
//使用流对集合进行筛选,成绩小于56的不要
list.stream().filter(x->x.getScore()>56).forEach(System.out::println);
//获取所有的名字
list.stream().map(x->x.getName()).forEach(System.out::println);
}
}
//其他方法的写法举个例子
//filter 筛选出分数高于70的学生
list.stream().filter(x->x.getScore()>70).forEach(System.out::println);
//limit 只去三个学生
list.stream().limit(3).forEach(System.out::println);
//skip 跳过前面五个去后面的学生
list.stream().skip(5).forEach(System.out::println);
//distinct 去重复
list.stream().distinct().forEach(System.out::println);
//sorted 排序,这里是默认排序,如果要自定义排序则在括号里面写上比较方法的lamdba表达式
list.stream().sorted().forEach(System.out::println);
//map 取出所有学生的名字
list.stream().map(o->o.getName()).forEach(System.out::println);
//parallel 换成多线程流
list.parallelStream().forEach(System.out::println);
//forEach
//min 通过比较分数的方式取得最小的那个学生
Optional<Student>m1=list.stream().min((e1,e2)->Double.compare(e1.getScore(), e2.getScore()));
System.out.println(m1.get());
//max 取得最大的
Optional<Student>m12=list.stream().max((e1,e2)->Double.compare(e1.getScore(), e2.getScore()));
System.out.println(m12.get());
//count 统计学生个数
long count=list.stream().count();
System.out.println("学生数量"+count);
//reduce 把所有的分数都加起来,前面map去除所有学生的分数,后面reduce把所有分数都加起来,(x,y 分别指的是两个变量,)
Optional<Double> sum = list.stream() .map(e->e.getScore()) .reduce((x,y)->x+y);
System.out.println(sum.get());
lambda表达式语句简单,但是句法独特,逻辑性比较高,所以要使用熟练的话就得刻意让自己时时刻刻想着自己正在写的方法是否可以用lambda表达式代替