lambda及stream学习
今日板砖,见lambda,不知其然遂不以为意。后又数现之,于是乎查之,究之,学之。半晌,豁然开朗!
lambda
lambda可以理解为一个匿名函数,可以将函数作为参数传入方法中,语法:() -> {}
():用来描述参数列表
->:lambda运算符
{}:用来描述方法体
对比
//1.原始创建线程方法
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("原始创建线程方法");
}
});
thread.start();
// new Thread()括号中存储的是实现了Runnable接口的一个匿名内部类;
//2. lambda创建线程方式
Thread thread1 = new Thread(()-> System.out.println("lambda线程方式"));
thread1.start();
//可以理解为,lambda创建了一个实现了Runnable接口的匿名内部类,()代表没有传递参数; System.out.println("lambda线程方式")是run()方法具体的逻辑;
lambda是针对函数式接口的一种快捷实例化方式,函数式接口为有且只有一个抽象方法的接口。使用lambda表达式,无需用对象实现接口,再继承重写抽象方法,直接通过()->{},传递参数,自定义逻辑,即可创建匿名内部类;
代码说明
-
无参无返回
/** * 测试无返回值无参数 */ @FunctionalInterface public interface LambdaNoRNoP { void testNoRNop(); } //无参无返回 LambdaNoRNoP lam1 = ()->{System.out.println("hello");};//创建一个匿名内部类,重写testNoRNop()方法 lam1.testNoRNop();
-
有参数有返回值
/** * 测试有返回值多个参数 */ @FunctionalInterface public interface LambdaRMulP { int testRMulP(int a ,int b); } //有返回值,多个参数 LambdaRMulP lam6 = (int a ,int b )->{ return a+b; }; System.out.println(lam6.testRMulP(1,2));
代码精简
- 由于在接口的抽象方法中,已经定义了参数数量和类型,所以在lambda中,参数类型可以省略
- 如果只有一个参数,小括号可以省略
- 如果方法体中只有一条语句,大括号可以省略
//参数类型精简
LambdaNoRMulP lam1 = (a,b)->{System.out.println(a);};
lam1.testNoRMulP(1,2);
//小括号精简
LambdaNoRSingleP lam2 = a -> {System.out.println(a);};
//大括号精简
LambdaNoRSingleP lam3 = a -> System.out.println(a);
方法引用
可以将lambda方法的实现,指向一个完整的方法,可以理解为解耦;
语法: 方法归属者::方法名
方法归属者:如果是静态方法,归属者就是类,如果是非静态方法,归属者就是对象。
要求:参数数量和类型一级返回值要和接口中定义的方法一致
public class Test{
private static int change(int a){
return a*2;
}
}
LambdaRSingleP lam2 = a-> a*2;
//等同于
LambdaRSingleP lam1 = a-> change(a);//lambda的实现a*2和change()返回值一致,可以直接引用change(a)方法
//等同于
LambdaRSingleP lam3 =Test::change;//lambda表达式是传入一个int值,返回两倍的值,和Test类中的change方法逻辑一致,可以直接引用;
stream学习
stream是java8中用来操作集合的,可以理解为另类的iterator,可以对其中元素进行操作。
举例说明
//筛选集合中满足要求的数据
List<User> userList = new ArrayList<>();
User user1 = new User("cz1",18);
User user2 = new User("cz2",19);
User user3 = new User("cz3",20);
userList.add(user1);
userList.add(user2);
Stream<User> stream = userList.stream();//将list转为stream流
Stream<User> userStream = stream.filter(o -> o.getAge() > 19);//过滤流中满足要求的数据,生成新的流
List<User> collect = userStream.collect(Collectors.toList()); // 将过滤的流转为集合
分析filter()方法源码
//filter方法传入的是一个Predicate<T>接口的实现类
Stream<T> filter(Predicate<? super T> predicate);
@FunctionalInterface //说明是个函数时接口,抽象方法接收一个对象,返回一个boolean值
public interface Predicate<T> {
boolean test(T t);
}
常用操作
数据操作
-
map 集合对象中的某个元素再转为集合
public static void testMap(List<User> userList){ List<String> collect = userList.stream().map(o -> o.getName()).collect(Collectors.toList());//获取姓名集合 List<String> collect2 = userList.stream().map(User::getName).collect(Collectors.toList());//获取姓名集合 collect.forEach(o->System.out.println(o));//打印对象 }
-
flatMap 流元素合并
public static void testFlatMap(List<User> userList1 , List<User> userList2){ List<List<User>> lists = new ArrayList<>(); lists.add(userList1); lists.add(userList2); //将集合里的元素(集合)转为流,再将流组合为一个大的集合 List<User> collect = lists.stream().flatMap(item -> item.stream()).collect(Collectors.toList()); //合并集合 collect.forEach(System.out::println); }
-
distinct 去重
//测试distinct 去重 public static void testDistinct(){ List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(1); List<Integer> collect = list.stream().distinct().collect(Collectors.toList()); collect.forEach(o-> System.out.println(o)); }
-
sorted 排序
//测试sorted 排序 public static void testSort(){ List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(1); List<Integer> collect = list.stream().sorted((o1, o2) -> o1 - o2).collect(Collectors.toList());//升序排序 List<Integer> collect2 = list.stream().sorted((o1, o2) -> o2 - o1).collect(Collectors.toList());//降序排序 }
-
limit 限流,只取几个元素
//测试limit限读
public static void testLimit(){
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(1);
List<Integer> collect = list.stream().limit(1).collect(Collectors.toList());
System.out.println(collect.size());
}
-
skip 跳过读取
//测试skip 跳过读取操作 public static void testSkip(){ List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(1); List<Integer> collect = list.stream().skip(2).collect(Collectors.toList()); collect.forEach(o-> System.out.println(o)); }
Collectors收集器
- toMap 对象元素转map集合
//测试collect收集器 toMap
public static void testCollectToMap(List<User> userList){
//以元素的name作为k,age作为v转为map集合
Map<String, Integer> collect = userList.stream().collect(Collectors.toMap(User::getName, User::getAge));
collect.forEach((o1,o2)-> System.out.println("K:"+o1+":V:"+o2));
}
-
toSet 转为不可重复集合
//测试collect收集器 toSet //不可重复 public static void testCollectToSet(List<Integer>list){ Set<Integer> collect = list.stream().collect(Collectors.toSet()); collect.forEach(System.out::println); }
-
groupingBy 集合对象分组
//测试groupingBy 分组 public static void testCollectGroupingBy(List<User> list){ Map<String, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getName)); collect.forEach((o1,o2)-> System.out.println("K:"+o1+"--V:"+o2)); }
-
maxBy 取集合最大元素
//测试maxBy 获取最大元素 public static void testMaxBy(List<User> list){ //获取user对象中年龄最大的 Optional<User> collect = list.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect.get());//拿到user对象 }
-
minBy 取集合最小元素
//测试minBy 获取最小元素 public static void testMinBy(List<User> list){ Optional<User> collect = list.stream().collect(Collectors.minBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect.get()); }
-
mapping 获取元素的某个属性的集合
//测试mapping隐射取值 public static void testMapping(List<User> list){ List<String> collect = list.stream().collect(Collectors.mapping(User::getName,Collectors.toList())); //等同于 List<String> collect1 = list.stream().map(o -> o.getName()).collect(Collectors.toList()); collect1.forEach(o-> System.out.println(o)); }
-
match 判断集合是否匹配
//测试match //allMatch--集合内所有元素都满足返回true //anyMatch--任意一个元素满足就返回true //noneMatch--没有元素满足就返回true public static void testMatch(List<User> list){ public static void testMatch(List<User> list){ boolean b = list.stream().allMatch(o -> o.getAge() > 19);//判断集合中的所有用户年龄是否都大于19 System.out.println(b); } }
常用操作
-
list对对象的某个元素求和
//测试match //allMatch--集合内所有元素都满足返回true //anyMatch--任意一个元素满足就返回true //noneMatch--没有元素满足就返回true list.stream() .map(o -> o.getAmount()) //获取对象中的数量 .filter(o -> Objects.nonNull(o)) //过滤掉null值,不然求和会报错 .reduce(BigDecimal.ZERO, BigDecimal::add); //累加器,第一个参数是初始化值;第二个参数是累加器,可以自定义