(JAVA8新特性) -> (lambda表达式学习心得【学习日记】)

2019.4.17

提炼出了对自己有用的东西,记录了学习过程便于复习。不过例子都来自于参考文章,链接已经在文中贴出。

1. 学习了lamda表达式,简单粗暴的语法糖,被它的功能强大所震撼。

①基础的用法比如匿名函数

//1. 接受2个参数(数字),并返回他们的差值 
(x, y) -> x – y 

//2. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y  

//3. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) 
(String s) -> System.out.print(s)  

②遍历,这里player是迭代的对象名,会根据集合类型自动获取类型,相当于常用for循环里常命名的 i 变量 

// 遍历输出
players.forEach((player) -> System.out.print(player + "; "));

③匿名内部类,可以用lambda表达式匿名实现其接口方法(不详述,见下方④举例)

④排序

// 1.1 使用匿名内部类根据 name 排序 players  
Arrays.sort(players, new Comparator() {  
    @Override  
    public int compare(String s1, String s2) {  
        return (s1.compareTo(s2));  
    }  
});  

// 1.2 如果使用 lambda expression 排序 players  
Comparator sortByName = (String s1, String s2) -> (s1.compareTo(s2));  
Arrays.sort(players, sortByName);  
  
// 1.3 也可以采用如下形式:  
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));  

这里就用一个lambda表达式创建了比较器对象,并为其指定行为。排序时传入Arrays.sort()即可

再举一个例子

// 使用匿名内部类根据 name lenght 排序 players  
Arrays.sort(players, new Comparator() {  
    @Override  
    public int compare(String s1, String s2) {  
        return (s1.length() - s2.length());  
    }  
});  

参考链接:Java中Lambda表达式的使用

2. Consumer接口

它是JAVA 8的新特性,语义上是消费的意思,可以输入某个对象,做一些列和它有关的操作,比如给某个JavaBean(例如Student)的平均分做运算,在控制台输出它的值。消费的概念与消息队列相似,可以根据传入的参数,执行特定的业务功能。

上面的链接讲了批量操作集合对象的例子,在Consumer对象中定义好处理行为即可,如

System.out.println("给程序员加薪 5% :");  
Consumer giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());  
  
javaProgrammers.forEach(giveRaise);  // 批量操作java程序员集合(List,Set等都可以)

注意Person是一个JavaBean,有工资字段Salary。那么Consumer 则定义了对于每一个输入的Person类对象e,调用 setSalary() 方法,为每个对象的工资字段乘以权值 1.05。最后在forEach中传入消费者对象,则完成了JavaBean集合的批量操作。

参考链接:JAVA8 Consumer接口

3. Stream

Stream是对集合的包装,通常和lambda一起使用,这点让Stream看起来用些类似Iterator。

同时你可以添加过滤器指定哪些对象要批量操作,或者通过max,min等方法获取集合最值以及统计数据。

举例如下

System.out.println("下面是月薪超过 $1,400 的PHP程序员:")  
phpProgrammers.stream()  
          .filter((p) -> (p.getSalary() > 1400))  
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));  

或者用lambda表达式声明多种过滤器对象

// 定义 filters  
Predicate ageFilter = (p) -> (p.getAge() > 25);  
Predicate salaryFilter = (p) -> (p.getSalary() > 1400);  
Predicate genderFilter = (p) -> ("female".equals(p.getGender()));  
  
System.out.println("下面是年龄大于 24岁且月薪在$1,400以上的女PHP程序员:");  
phpProgrammers.stream()  
          .filter(ageFilter)  
          .filter(salaryFilter)  
          .filter(genderFilter)  
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));  

获取你关心的比较方式中的最值

System.out.println("工资最低的 Java programmer:");  
Person pers = javaProgrammers  
          .stream()  
          .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))  
          .get()  

也可以把批量处理的结果集输出为字符串,或重组为新的集合

System.out.println("将 PHP programmers 的 first name 拼接成字符串:");  
String phpDevelopers = phpProgrammers  
          .stream()  
          .map(Person::getFirstName)  
          .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)     
  
System.out.println("将 Java programmers 的 first name 存放到 Set:");  
Set javaDevFirstName = javaProgrammers  
          .stream()  
          .map(Person::getFirstName)  
          .collect(toSet());  
  
System.out.println("将 Java programmers 的 first name 存放到 TreeSet:");  
TreeSet javaDevLastName = javaProgrammers  
          .stream()  
          .map(Person::getLastName)  
          .collect(toCollection(TreeSet::new));  

甚至支持并行和统计

System.out.println("计算付给 Java programmers 的所有money:");  
int totalSalary = javaProgrammers  
          .parallelStream()  
          .mapToInt(p -> p.getSalary())  
          .sum();  
//计算 count, min, max, sum, and average for numbers  
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
IntSummaryStatistics stats = numbers  
          .stream()  
          .mapToInt((x) -> x)  
          .summaryStatistics();  
  
System.out.println("List中最大的数字 : " + stats.getMax());  
System.out.println("List中最小的数字 : " + stats.getMin());  
System.out.println("所有数字的总和   : " + stats.getSum());  
System.out.println("所有数字的平均值 : " + stats.getAverage());   

4. 还有一种双冒号的写法引文没有专门讲

对于java程序员集合的每个对象,执行命名域System.out的print函数,连变量游标都省略了。

javaProgrammer.foreach(System.out::print);

以及上文例子中有在批处理中,把这个类对象的某个值域单独提出来

String phpDevelopers = phpProgrammers  
          .stream()  
          .map(Person::getFirstName)  
          .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)   

所以 :: 起到调用函数,和调用值域的作用。

你可能感兴趣的:(资料搜集,后端)