Java中Lambda简析笔记

Java中的Lambda简析笔记


参考资料

  • 《Java编程思想(第四版)》
  • Java学习网站:How2java.cn
  • 大佬博客:Java中的Lambda

介绍Lambda,首先应从普通方法,匿名类以及Lambda方式的比较中清晰为什么要有Lambda,见如下题目:

例题:找出满足条件的Hero对象,如下:

初始化后的集合:
[Hero [name=hero 0,hp=77.0,damage=28]
,Hero [name=hero 1,hp=984.0,damage=89]
,Hero [name=hero 2,hp=350.0,damage=19]
,Hero [name=hero 3,hp=731.0,damage=41]
,Hero [name=hero 4,hp=489.0,damage=33]
]

筛选出 hp>100 && damange<50的英雄
Hero [name=hero 2,hp=350.0 damage=19]
Hero [name=hero 3,hp=731.0 damage=41]
Hero [name=hero 4,hp=489.0 damage=33]
public class Hero implements Comparable<Hero>{
    public String name;
    public float hp;
    public int damage;
        
    public Hero(){
           
    }
    
    public Hero(String name) {
        this.name =name;
    }
    
    //初始化name,hp,damage的构造方法
    public Hero(String name,float hp, int damage) {
        this.name =name;
        this.hp = hp;
        this.damage = damage;
    }
    @Override
    public int compareTo(Hero anotherHero) {
        if(damage<anotherHero.damage)
            return 1; 
        else
            return -1;
    }
    @Override
    public String toString() {
        return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
    }
       
}

一、筛选数据的方法

筛选方法1:普通方法

  • 实现filter()方法,对hero列表进行遍历检查。
public void filter(List<Hero> heros){
    for(Hero hero:heros){
        if(hero.hp>100 && hero.damage<50)
            System.out.println(hero);
    }
}

筛选方法2:匿名类方法

  • 利用匿名类HeroChecker检查hero是否符合要求,符合要求则输出

    public interface HeroChecker{
        public boolean test(Hero h);
    }
    
  • 在类中具体实现匿名类接口,检查hero

    public HeroChecker checker = new HeroChecker(){
        @Override
        public boolean test(Hero h){
            return (h.hp>100 && h.damage<50);
        }
    }
    
  • 在filter()函数中实现hero的遍历检查

    public static void filter(List<Hero> heros,HeroChecker checker){
        for(Hero h:heros){
            if(checker.test(h)){
                System.out.println(h);
            }
        }
    }
    

筛选方法3:Lambda方式

题外:Lambda是由匿名类一点一点演变过来的

Lambda语法

基本的语法:

  • (parameters)->expression
  • (parameters)->{statements;}
// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

二、设置排序集合方式

//先做一个字符串数组strs
String[] strs = {"LPB","ZXF","BYD","ZZY",
                 "CHL","PKF","HHB","HY"};

2.1、使用匿名内部类排序

Arrays.sort(strs,new Comparator<String>(){
    @Override
    public int compare(String s1,String s2){
        return s1.compareTo(s2);
    }
});

2.2、使用Lambda排序集合

//lambda expression排序strs
Compare<String> sortByName = (String s1,String s2)->
    s1.compareTo(s2);
//省略,一行排序
Arrays.sort(strs,(String s1,String s2)->
            s1.compareTo(s2));

三、Lambdas和Streams的合作

​ Streams是对集合的包装,常与lambda一起使用;使用lambda可支持许多的操作如map、filter、limit、sorted、count、collect等等。

Streams使用懒运算,其并不会真正读取到数据,遇到如getFirst()如此的方法便会结束链式语法。

注:Streams操作也可以设为并行的,将stream()换为parallelStream()即可。

实体类Person:

public class Person{
    private String firstName,lastName,job,gender;
    private int salary,age;
    public Person(String firstName,String lastName,
                 String job,String gender,int salary,
                  int age){
        this.firstName = firstName;
        this.lastName = lastName;
        this.job = job;
        this.gender = gender;
        this.salary = salary;
        this.age = age;
    }
    //省略get方法以及set方法
}

我们先实现两个数组,分别表示Java程序员和C++程序员

List<Person> javaProgrammers = new ArrayList<Person>() {  
  {  
    add(new Person("Elsdon", "Jaycob", "Javaprogrammer", "male", 43, 2000));  
    add(new Person("Tamsen", "Brittany", "Javaprogrammer", "female", 23, 1500));  
    add(new Person("Floyd", "Donny", "Javaprogrammer", "male", 33, 1800));  
    add(new Person("Sindy", "Jonie", "Javaprogrammer", "female", 32, 1600));  
    add(new Person("Vere", "Hervey", "Javaprogrammer", "male", 22, 1200));  
    add(new Person("Maude", "Jaimie", "Javaprogrammer", "female", 27, 1900));  
    add(new Person("Shawn", "Randall", "Javaprogrammer", "male", 30, 2300));  
    add(new Person("Jayden", "Corrina", "Javaprogrammer", "female", 35, 1700));  
    add(new Person("Palmer", "Dene", "Javaprogrammer", "male", 33, 2000));  
    add(new Person("Addison", "Pam", "Javaprogrammer", "female", 34, 1300));  
  }  
};  
  
List<Person> cppProgrammers = new ArrayList<Person>() {  
  {  
    add(new Person("Jarrod", "Pace", "Cppprogrammer", "male", 34, 1550));  
    add(new Person("Clarette", "Cicely", "Cppprogrammer", "female", 23, 1200));  
    add(new Person("Victor", "Channing", "Cppprogrammer", "male", 32, 1600));  
    add(new Person("Tori", "Sheryl", "Cppprogrammer", "female", 21, 1000));  
    add(new Person("Osborne", "Shad", "Cppprogrammer", "male", 32, 1100));  
    add(new Person("Rosalind", "Layla", "Cppprogrammer", "female", 25, 1300));  
    add(new Person("Fraser", "Hewie", "Cppprogrammer", "male", 36, 1100));  
    add(new Person("Quinn", "Tamara", "Cppprogrammer", "female", 21, 1000));  
    add(new Person("Alvin", "Lance", "Cppprogrammer", "male", 38, 1600));  
    add(new Person("Evonne", "Shari", "Cppprogrammer", "female", 40, 1800));  
  }  
};

3.1、forEach迭代

  • 迭代输出列表
javaProgrammers.forEach((p) -> System.out.printf("%s,%s;",
                                                 p.getFirstName,p.getLastName()));
cppProgramers.forEach((p) -> System.out.printf("%s,%s;",
                                               p.getFirstName(),p.getLastName()));
  • 给所有程序员加薪,增加50%工资
Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 2 
                                              + e.getSalary());  
javaProgrammers.forEach(giveRaise);  
phpProgrammers.forEach(giveRaise);  

3.2、过滤器filter()

  • 使用过滤器显示集合中符合特定条件的对象
//显示月薪超过1000美元的Java程序员
javaProgrammers.stream()
    .filter((p)->(p.getSalary()>1000))
    .forEach((p)->System.out.printf("%s,%s;",p.getFirstName(),p.getLastName()));
  • 此外还可以定义过滤器,通过重用过滤器来执行其他的操作
Predicate<Person> ageFilter = (p)->(p.getAge()>25);
Predicate<Person> salaryFilter = (p)->(p.getSalary()>1000);
Predicate<Person> genderFilter = (p)->("female".equals(p.getGender()));

//输出年龄大于25、月薪在1000以上的女cpp程序员
cppProgrammers.stream()
    .filter(ageFilter)
    .filter(salaryFilter)
    .filter(genderFilter)
    .forEach((p)->System.out.printf("%s,%s;",p.getFirstName(),p.getLastName()));

//输出年龄大于25、月薪在1000以上的女java程序员
javaProgrammers.stream()
    .filter(ageFilter)
    .filter(salaryFilter)
    .filter(genderFilter)
    .forEach((p)->System.out.printf("%s,%s;",p.getFirstName(),p.getLastName()));

使用 limit(int n); 函数可以实现是输出前 n 个对象元素;

另外我们在stream中同样可以使用 sorted()实现排序:

//根据name排序,并输出前5个Java程序员
List<Person> sortedJavaProgrammers = javaProgrammers.stream()
    .sorted((p1,p2)->(p.getFirstName().compareTo(p2.getFirstName())))
    .limit(5)
    .collect(toList());

sortedJavaProgrammers.forEach((p)->System.out.printf(
    "%s %s,%n",p.getFirstName(),p,getLastName()));

3.3、min、max方法

当然,我们可以通过过滤器filter()只过滤出最小或最大的值,但速度肯定是比直接用min或max方法慢的

//输出工资最低的 Java 程序员 
Person pers = javaProgrammers  
          .stream()  
          .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))  
          .get()  
  
System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary())  
  
//输出工资最高的 Java 程序员 
Person person = javaProgrammers  
          .stream()  
          .max((p, p2) -> (p.getSalary() - p2.getSalary()))  
          .get()  
  
System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary())

3.4、利用map和collect方法存放结果集

我们可以将map()和 collect()结合,将结果集存放到一个字符串、Set或TreeSet中:

//将 cpp程序员 的 first name 拼接成字符串
String phpDevelopers = phpProgrammers  
          .stream()  
          .map(Person::getFirstName)  
          .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)     
  
//将 Java程序员 的 first name 存放到 Set 
Set<String> javaDevFirstName = javaProgrammers  
          .stream()  
          .map(Person::getFirstName)  
          .collect(toSet());  
  
//将 Java程序员 的 first name 存放到 TreeSet
TreeSet<String> javaDevLastName = javaProgrammers  
          .stream()  
          .map(Person::getLastName)  
          .collect(toCollection(TreeSet::new));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值