# lambdaLearnDemo **Repository Path**: justin98/lambda-learn-demo ## Basic Information - **Project Name**: lambdaLearnDemo - **Description**: lambda表达式练习 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-03-04 - **Last Updated**: 2022-05-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # lambdaLearnDemo ## 介绍 lambda表达式练习 lambda表达式是表达接口函数的实现 函数式接口只能有一个抽象方法,可包含多个static方法 lambda表达式 ```java val -> System.out.println(val); ``` `->`左边为参数,右边为函数体 ### 不使用lambda来实现接口的打印 ```java package com.justin.java8; /** * @author jgn */ public class LambdaDemo1 { interface Printer{ void printer(String val); } public void printSomething(String something ,Printer printer){ printer.printer(something); } public static void main(String[] args) { LambdaDemo1 lambdaDemo1 = new LambdaDemo1(); String some = "Justin"; // 无lambda实现 /* Printer printer = new Printer() { public void printer(String val) { System.out.println(val); } };*/ // 使用lambda实现 Printer printer = (String val) ->{ System.out.println(val); }; lambdaDemo1.printSomething(some,printer); } } ``` ### lambda表达式的简化 ```java Printer printer = (String val) ->{ System.out.println(val); }; lambdaDemo1.prinSomething(some,printer); ``` 去参数的对象类型 ```java Printer printer = (val) ->{ System.out.println(val); }; lambdaDemo1.printSomething(some,printer); ``` 去参数的小括号 ```java Printer printer = val ->{ System.out.println(val); }; lambdaDemo1.printSomething(some,printer); ``` 要执行的语句只有一句的话可以去大括号变成一句 ```java Printer printer = val -> System.out.println(val); lambdaDemo1.printSomething(some,printer); ``` 可代替对象放入放入方法的参数里 ```java lambdaDemo1.printSomething(some,val -> System.out.println(val)); ``` 当实现的接口没有任何参数时 ```java interface Printer{ void printer(); } () -> System.out.println("") ``` 如果为控制台打印使用特有的lambda表达式进行书写 ```java lambdaDemo1.printSomething(some, System.out::println); ``` 小结 - 箭头左侧没有指定参数类型,编译器会从接口方法的形参中推断其类型 - 只有一个参数时,可省略参数的括号 - 函数体只有一行可以省略花括号(大括号) ### Java Stream的转换 ```java /** * stream 流式处理 * @author jgn */ public class StreamDemo1 { public static void main(String[] args) { List cars = Arrays.asList("aodi", "dazhong", "beichi", "suv"); List sorted = cars.stream()// list转流 .filter(s -> s.startsWith("d"))// 过滤 .map(String::toUpperCase)// 映射 大写处理 .sorted()// 排序 .collect(Collectors.toList());// 流转回list System.out.println(sorted); // 数组转流 String[] array = {"system","out","sorted"}; Stream names = Stream.of(array); // 集合类转流 List namelist = Arrays.asList("map", "set", "stack"); Stream stream = namelist.stream(); // 文件转流 Stream lines = Files.lines(Paths.get("file.txt")); } } ``` ### 谓词逻辑与谓词 ```java /** * Returns a stream consisting of the elements of this stream that match * the given predicate. * *

This is an intermediate * operation. * * @param predicate a non-interfering, * stateless * predicate to apply to each element to determine if it * should be included * @return the new stream */ Stream filter(Predicate predicate); ``` predicate 是谓语/断言的意思 >谓词逻辑和语言学所讲的「谓词」是相同的,都是“表达客体性质或关系的词项”。不过,谓词逻辑的谓词范围要小于语言学的谓词范围,因为谓词逻辑只是语言学逻辑的一个子集,除此之外,还有模态逻辑,情态逻辑,句链逻辑,内涵逻辑等 > >谓词:用来代替或者展示其客体性质、特征或者客体之间关系的词项 举个例子sql语句中的where and 就是一个谓词逻辑, ### 谓词逻辑的复用 通常情况下,filter函数中的lambda表达式就是一次性使用的谓词逻辑。 如果谓词逻辑要在多处使用,通常将它抽取出来单独定义到它所限定的主语实体中 ```java /** * 实体类 */ @Data @AllArgsConstructor public class Employee { private Integer id; private Integer age; //年龄 private String gender; //性别 private String firstName; private String lastName; // 谓语逻辑 /** * 年纪大于70的 */ public static Predicate ageGreaterThan70 = x -> x.getAge() >70; /** * 性别是男的 */ public static Predicate genderM = x -> x.getGender().equals("M"); } ``` 复用测试 ```java public class StreamFilterPredicate { public static void main(String[] args) { Employee e1 = new Employee(1,23,"M","Rick","Beethovan"); Employee e2 = new Employee(2,13,"F","Martina","Hengis"); Employee e3 = new Employee(3,43,"M","Ricky","Martin"); Employee e4 = new Employee(4,26,"M","Jon","Lowman"); Employee e5 = new Employee(5,19,"F","Cristine","Maria"); Employee e6 = new Employee(6,15,"M","David","Feezor"); Employee e7 = new Employee(7,68,"F","Melissa","Roy"); Employee e8 = new Employee(8,79,"M","Alex","Gussin"); Employee e9 = new Employee(9,15,"F","Neetu","Singh"); Employee e10 = new Employee(10,45,"M","Naveen","Jain"); List employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); // 过滤年龄大于70且为男性的员工 ,一次性的谓语逻辑 List employeesList = employees.stream() .filter(e -> e.getAge() > 70 && e.getGender().equals("M")) .collect(Collectors.toList()); // 逻辑断言的复用 // and List employeesListAnd = employees.stream() .filter(Employee.ageGreaterThan70.and(Employee.genderM)).collect(Collectors.toList()); // or List employeesListOr = employees.stream() .filter(Employee.ageGreaterThan70.or(Employee.genderM)).collect(Collectors.toList()); // negate 取反 List employeesListNegate = employees.stream() .filter(Employee.ageGreaterThan70.or(Employee.genderM).negate()).collect(Collectors.toList()); System.out.println(employeesList); System.out.println(employeesListAnd); System.out.println(employeesListOr); System.out.println(employeesListNegate); } } ``` ### map 的数据转换 map进行数据格式状态的转换,和类型的转换, map flatmap 都是无状态的操作 只进行一步操作 ```java List alpha = Arrays.asList("Monkey","Lion","Giraffe","Lemur"); // 不使用管道流,将字母都转为大写 List alphaUpper = new ArrayList<>(); for (String s : alpha) { alphaUpper.add(s.toUpperCase()); } System.out.println("不用管道流:"+alphaUpper); List collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList()); System.out.println("用管道流:"+collect); List lengths = alpha.stream().map(String::length).collect(Collectors.toList()); System.out.println("获取每个元素的长度:"+lengths); List collect1 = collect.stream().map(String::toLowerCase).collect(Collectors.toList()); System.out.println(collect1); // 字符串数组 Stream.of("Monkey","Lion","Giraffe","Lemur").mapToInt(String::length).forEach(System.out::println); ``` 实现复杂的流式映射,使用map或peek map与peek的区别 - map要返回值 - peek不需要 ```java List employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); // 年龄+1,M变为male F变为female // List collect = employees.stream().map(x -> { // x.setAge(x.getAge() + 1); // x.setGender(x.getGender().equals("M") ? "male" : "female"); // return x; // }).collect(Collectors.toList()); List collect = employees.stream().peek(x -> { x.setAge(x.getAge() + 1); x.setGender(x.getGender().equals("M") ? "male" : "female"); }).collect(Collectors.toList()); System.out.println(collect); ``` ### faltMap faltMap 就是将多个分开的管道数据展开到一个管道 ```java List words = Arrays.asList("hello","word","justin"); words.stream().map(w -> Arrays.stream(w.split(""))).forEach(System.out::println); // java.util.stream.ReferencePipeline$Head@7699a589 // java.util.stream.ReferencePipeline$Head@58372a00 // java.util.stream.ReferencePipeline$Head@4dd8dc3 words.stream().flatMap(w ->Arrays.stream(w.split(""))).forEach(System.out::println); ``` ### 有状态和无状态 状态通常代表操作的公共的数据,需要进行额外的存储,比如存在redis或内存,通常会被多人、多用户多线程多次操作会涉及到状态的管理