目录
Lambda表达式
Lamada是一个匿名函数,可以理解为一段可传递的代码。
格式
->:lamda操作符 或 箭头操作符
->左边:lamda形参列表,其实就是接口中的抽象方法的形参列表。
lambda形参列表的参数类型可以省略,如果lambda形参列表只有一个参数,则可以省略()
->右边:lamda体,其实就是重写的抽象方法的方法体。
lamda应该使用一对{}包裹,如果lamda体只有一条执行语句(可能return语句)
可以省略这一对{}和return
本质
作为函数式接口的实例。
举例
//->为lambda操作符
Runnable r1 =() -> System.out.println("我爱北京天安门");
r1.run();
Comparator<Integer> com2 = (o1,o2) ->Integer.compare(o1,o2);
int ans = com2.compare(12,21);
//方法引用 和上面的表达一样
Comparator<Integer> com3 = Integer::compare;
使用
//情况1:无参且无返回值
Runnable r2 = () -> System.out.println("lambda1");
r2.run();
//情况2:需要一个参数但无返回值
Consumer<String> con = (String s) -> {
System.out.println(s);
};
con.accept("lambda2");
//情况3:优化情况2,数据类型可以省略,因为可由编译器推断得出
Consumer<String> con1 = (s) -> {
System.out.println(s);
};
con1.accept("lambda3");
//情况4:Lambda若只需要一个参数,则参数的小括号可以省略
Consumer<String> con2 = s -> {
System.out.println(s);
};
con2.accept("lambda4");
//情况5:lambda需要两个或以上的参数,多条执行语句,并且可以有返回值
Comparator<Integer> com = (o1,o2) ->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
com.compare(12,21);
//情况6:当lamda体只有一条语句时,return与大括号若有,都可以省略
Comparator<Integer> com1 = (o1,o2) -> o1.compareTo(o2);
com1.compare(12,21);
函数式接口
如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。
//这个注解可以检查它是否是一个函数式接口
@FunctionalInterface
public interface MyInterface{
void method1();
}
内置的四个核心函数式接口
- void Consumer< T >:对类型为T的对象应用操作,包含方法:void accept(T t)
- T Supplier< T >:返回类型为T的对象,包含方法:T get()
- R Function<T,R>:对类型为T的对象应用操作,并返回R类型的结果。包含方法:R apply(T t)
- boolean Predicate< T >:确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t)
例子
Consumer:
public void happyTime(double money, Consumer<Double> con){
con.accept(money);
}
public void test(){
happyTime(500, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("花了"+aDouble);
}
});
happyTime(400,money -> System.out.println("又花了"+money));
}
Predicate:
public List<String> filterString(List<String> list, Predicate<String> pre){
ArrayList<String> filterList = new ArrayList<>();
for(String s:list){
if(pre.test(s)) filterList.add(s);
}
return filterList;
}
public void test(){
ArrayList<String> ll = new ArrayList<>();
ll.add("a");
ll.add("b");
ll.add("1");
ll.add("d");
List<String> strings = filterString(ll, s -> {
if (Character.isLetter(s.charAt(0))) return true;
return false;
});
System.out.println(strings);
}
方法引用
当要传递给Lambda体的操作已经有实现的方法时,可以使用方法引用。本质上就是lambda表达式,也是函数式接口的实例。
使用要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法一致。
例子
主要有三种调用
对象::非静态方法
类::静态方法
类::非静态方法
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("北京");
//此时发现Consumer中的accept()和PrintStream里的void println()有同一作用
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("哈哈哈");
//Supplier 不接收参数 返回一个值
String str="供应者";
Supplier<String> sup1 = () -> str.substring(0,1);
sup1.get();
//改为方法引用
Supplier<String> sup2 = str::trim;
构造器引用
Supplier<Employee> sup2 = Employee::new;
//<T,R>对类型为T的对象应用操作,并返回R类型的结果。
Function<Integer,Employee> func1 = id -> new Employee(id);
Employee e1 = func1.apply(1001);
数组引用,把数组看做是一个特殊的类。
//lambda表达式
Function<Integer,String[]> func1 = length -> new String[length];
String[] arr = func1.apply(10);
//数组引用
Function<Integer,String[]> func2 = String[] :: new;
Stream API
- Stream是实现对数据源(集合,数组等生成的元素序列)进行操作,计算的。
- Stream自己不会存储元素
- Stream不会改变源对象,相反会返回一个持有结果的新Stream
Stream的创建
//通过集合获取流
List<String> arr = Arrays.asList("a","b","c","d","e");
//返回一个顺序流 按照顺序取数据
Stream<String> stream = arr.stream();
//返回一个并行流 并行取数据
Stream<String> parallelStream = arr.parallelStream();
//通过数组获取流
int[] arr1 = new int[]{1,2,3,4,5,6};
IntStream stream1 = Arrays.stream(arr1);
//通过of()获取流
Stream.of(1,2,3,4,5,6);
//以上都是有限流 还可以创建无限流
//迭代 种子为0 lambda执行输入t返回t+2 限制只打印10个 对于每一个生成的数字方法引用println
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
//生成10个随机数
Stream.generate(Math::random).limit(10).forEach(System.out::println);
筛选与切片
- fliter(Predicate p):接收lambda,从流中排除某些元素。
- distinct():筛选,通过流所生成元素的hashCode()和equals()去除重复元素。
- limit(long maxSize):截断流,使其元素不超过给定数量。
- skip(long n):跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流,与limit(n)互补。
//通过数组获取流
int[] arr = new int[]{1,2,2,3,4,5,5,6};
//查询大于等于3的
IntStream stream = Arrays.stream(arr);
stream.filter(t -> t>=3).forEach(System.out::println);
//重新生成 使打印出的元素不超过3
IntStream stream1 = Arrays.stream(arr);
stream1.limit(3).forEach(System.out::println);
//去重
IntStream stream2 = Arrays.stream(arr);
stream2.distinct().forEach(System.out::println);
映射
map:
//通过数组获取流
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
//map 将所有转换为大写
strings.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
strings.stream().map(str -> str.toUpperCase()).forEach(s -> {System.out.println(s);});
//获取长度大于3的员工姓名
Stream<Object> objectStream = strings.stream().map(e -> Employee::getName);
objectStream.filter(name -> name.lengrh()>3).forEach(System.out::println);
flatmap:应用集合里面套集合
//将字符串中多个字符构成的集合转换为对应的Stream的实例
public static Stream<Character> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for(Character c:str.toCharArray()){
list.add(c);
}
return list.stream();
}
public static void main(String[] args) throws Exception {
//flatmap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流
//连成一个流
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
//调用map返回Stream<Stream<Character>>
Stream<Stream<Character>> streamStream = strings.stream().map(test::fromStringToStream);
//调用flatmap返回每个字符的Stream
final Stream<Character> characterStream = strings.stream().flatMap(test::fromStringToStream);
}
排序
List<Integer> integers = Arrays.asList(12, 32, 6, 21, 89, 13, 9);
//自然排序
integers.stream().sorted().forEach(System.out::println);
//比较器排序
integers.stream().sorted((o1,o2) -> {
return Integer.compare(o1,o2);
}).forEach(System.out::println);
integers.stream().sorted((e1,e2) -> Integer.compare(e1,e2)).forEach(System.out::println);
终止操作:匹配与查找
List<Integer> integers = Arrays.asList(12, 32, 6, 21, 89, 13, 9);
//allMatch:检查是否匹配所有元素
boolean b = integers.stream().allMatch(o -> o > 50);
//anyMatch:存在一个就算成功
boolean b1 = integers.stream().anyMatch(o -> o > 20);
//noneMatch:是否没有匹配的元素 有就返回false
boolean b2 = integers.stream().noneMatch(o -> o > 50);
//findFirst:返回第一个元素
Optional<Integer> first = integers.stream().findFirst();
//finAny:返回流中的任意元素
Optional<Integer> any = integers.stream().findAny();
//count:返回元素总个数
long count = integers.stream().filter(e -> e > 20).count();
//max:返回流中最大值
Optional<Integer> max = integers.stream().max(Double::compare);
//min:返回流中最大值
Optional<Integer> min = integers.stream().min(Double::compare);
终止操作:规约
List<Integer> integers = Arrays.asList(12, 32, 6, 21, 89, 13, 9);
//reduce:可以将流中元素反复结合,得到一个值并返回此值 第一个参数相当于初始值 第二个参数是对其中元素的操作
Integer reduce = integers.stream().reduce(0, Integer::sum);
Optional<Integer> reduce1 = integers.stream().reduce((d1, d2) -> d1 + d2);
System.out.println(reduce);
System.out.println(reduce1);
终止操作:收集
List<Integer> integers = Arrays.asList(12, 32, 6, 21, 89, 13, 9);
//collect:将流转换为其它形式,比如List Set Map等
List<Integer> collect = integers.stream().filter(o -> o > 50).collect(Collectors.toList());
Optional类
可以保证类其中的对象不为空
toy toy = new toy();
//创建对象 此时不会报错
Optional<toy> toy1 = Optional.of(toy);
toy=null;
//此时会报错
Optional<toy> toy2 =Optional.of(toy);
//ofNullable里可以为null 故不会报错
Optional<toy> toy3 = Optional.ofNullable(toy);
//OrElse:如果有值则将其返回,否则返回指定的other对象
toy toy4 = toy3.orElse(new toy("玩具狮子"));