Lambda使用案例

Lambda

在对Java8 发布的Lambda表达式进行一定了解之后,发现Lambda最核心的就是 结合Stream API对集合数据的遍历、提取、过滤、排序等一系列操作的简化,以一种函数式编程的方式,对集合进行操作。下面总结了几种常用的示例Demo;
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)

1.用lambda表达式实现Runnable

lambda表达式替换了原来匿名内部类的写法,没有了匿名内部类繁杂的代码实现,而是突出了,真正的处理代码。最好的示例就是 实现Runnable 的线程实现方式了: 用() -> {}代码块替代了整个匿名类

@Test
public void test(){
    //old
    new Thread((new Runnable() {
        @Override
        public void run() {
            System.out.println("匿名内部类 实现线程");
        }
    })).start();
    //lambda
    new Thread( () -> System.out.println("java8 lambda实现线程")).start();
}

结果:

以下demo 使用的 Person 实体 以及 person list:

@Data
@ToString
@Accessors(chain = true)
public class Person {
    private String name;
    private int age;
    private String sex;
}
 
 
private List<Person> getPersonList(){
        Person p1 = new Person().setName("liu").setAge(22).setSex("male");
        Person p2 = new Person().setName("zhao").setAge(21).setSex("male");
        Person p3 = new Person().setName("li").setAge(18).setSex("female");
        Person p4 = new Person().setName("wang").setAge(21).setSex("female");
        List<Person> list = Lists.newArrayList();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        return list;
    }

2.forEach 遍历集合

使用 forEach方法,直接通过一行代码即可完成对集合的遍历:

@Test
    public void test1(){
        List<Person> list = getPersonList();
        list.forEach(person -> System.out.println(person.toString()));
    }
结果
    Person(name=liu, age=22, sex=male)
    Person(name=zhao, age=21, sex=male)
    Person(name=li, age=18, sex=female)
    Person(name=wang, age=21, sex=female)
 双冒号::  表示方法引用,可以引用其他方法
    @Test
    public void test2(){
        List<Person> list = getPersonList();
        Consumer<Person> changeAge = e -> e.setAge(e.getAge() + 3);
        list.forEach(changeAge);
        list.forEach(System.out::println);
    }
 
    结果:
    Person(name=liu, age=25, sex=male)
    Person(name=zhao, age=24, sex=male)
    Person(name=li, age=21, sex=female)
    Person(name=wang, age=24, sex=female)

3.filter 对集合进行过滤

filter 可以根据传入的 Predicate 对象,对集合进行过滤操作,Predicate 实质就是描述了过滤的条件:

@Test
    public void test3(){
        List<Person> list = getPersonList();
        list.stream().filter(e -> e.getAge() > 20)
                     .forEach(e -> System.out.println(e.toString()));
    }
       
    结果:
    Person(name=liu, age=22, sex=male)
    Person(name=zhao, age=21, sex=male)
    Person(name=wang, age=21, sex=female)
    当需要通过 多个过滤条件对集合进行过滤时,可以采取两种方式:

       1.可以通过调用多次filter 通过传入不同的 Predicate对象来进行过滤

       2.也可以通过 Predicate 对象的 and  or 方法,对多个Predicate 对象进行 且 或 操作

    @Test
    public void test4(){
        List<Person> list = getPersonList();
 
        Predicate<Person> ageFilter = e -> e.getAge() > 20;
        Predicate<Person> sexFilter = e -> e.getSex().equals("male");
 
        //多条件过滤
        list.stream().filter(ageFilter)
                     .filter(sexFilter)
                     .forEach(e -> System.out.println(e.toString()));
        System.out.println("----------------------------");
        // Predicate : and or
        list.stream().filter(ageFilter.and(sexFilter))
                     .forEach(e -> System.out.println(e.toString()));
    }
 
 
    结果:
    Person(name=liu, age=22, sex=male)
    Person(name=zhao, age=21, sex=male)
    ----------------------------
    Person(name=liu, age=22, sex=male)
    Person(name=zhao, age=21, sex=male)

4.limit 限制结果集的数据量

limit 可以控制 结果集返回的数据条数:返回三条数据,返回年龄>20的前两条数据

@Test
public void  test5(){
    List<Person> list = getPersonList();
    list.stream().limit(3).forEach(e -> System.out.println(e.toString()));

    System.out.println("----------------------------");
    list.stream().limit(2).filter(e -> e.getAge() > 20)
                 .forEach(e -> System.out.println(e.toString()));
}


结果:
Person(name=liu, age=22, sex=male)
Person(name=zhao, age=21, sex=male)
Person(name=li, age=18, sex=female)
----------------------------
Person(name=liu, age=22, sex=male)
Person(name=zhao, age=21, sex=male)

5. sorted 排序

通过sorted,可以按自定义的规则,对数据进行排序,可以用两种写法,分别按 年龄 和 姓名排序

@Test
public void test6(){
    List<Person> list = getPersonList();
    //年龄排序
    list.stream().sorted((p1,p2) -> (p1.getAge() - p2.getAge()))
                 .forEach(e -> System.out.println(e.toString()));
    //姓名排序
    System.out.println("----------------------------");
    list.stream().sorted(Comparator.comparing(Person::getName))
                 .forEach(e -> System.out.println(e.toString()));
}


结果:
Person(name=li, age=18, sex=female)
Person(name=zhao, age=21, sex=male)
Person(name=wang, age=21, sex=female)
Person(name=liu, age=22, sex=male)
----------------------------
Person(name=li, age=18, sex=female)
Person(name=liu, age=22, sex=male)
Person(name=wang, age=21, sex=female)
Person(name=zhao, age=21, sex=male)

6.max min 获取结果中 某个值最大最小的的对象

max min 可以按指定的条件,获取到最大、最小的对象,当集合里有多个满足条件的最大最小值时,只会返回一个对象。

如: 返回年龄最大的人

@Test
public void test7(){
    List<Person> list = getPersonList();
    // 如果 最大最小值 对应的对象有多个 只会返回第一个
    Person oldest = list.stream().max(Comparator.comparing(Person::getAge)).get();
    System.out.println(oldest.toString());
}


结果:
Person(name=liu, age=22, sex=male)

7.map 与 reduce也是两个十分重要的方法,
map:对集合中的每个元素进行遍历,并且可以对其进行操作,转化为其他对象,如将集合中的每个人的年龄增加3岁

@Test
public void test8(){
    List<Person> list = getPersonList();
    //将 每人的年龄 +3
    System.out.println("修改前:");
    list.forEach(e -> System.out.println(e.toString()));
    System.out.println("修改后:");
    list.stream().map(e -> e.setAge(e.getAge() + 3 ))
                 .forEach(e -> System.out.println(e.toString()));

}

结果:
修改前:
Person(name=liu, age=22, sex=male)
Person(name=zhao, age=21, sex=male)
Person(name=li, age=18, sex=female)
Person(name=wang, age=21, sex=female)
修改后:
Person(name=liu, age=25, sex=male)
Person(name=zhao, age=24, sex=male)
Person(name=li, age=21, sex=female)
Person(name=wang, age=24, sex=female)

reduce:也是对所有值进行操作,但它是将所有值,按照传入的处理逻辑,将结果处理合并为一个
如:将集合中的所有整数相加,并返回其总和

@Test
public void test9(){
    //第一个参数是上次函数执行的返回值(也称为中间结果),第二个参数是stream中的元素,
    // 这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数。
    //要注意的是:第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素

    //将所有人的年龄加起来 求和
    List<Integer> ages = Arrays.asList(2,5,3,4,7);
    int totalAge = ages.stream().reduce((sum,age) -> sum + age).get();

    System.out.println(totalAge);
    //带 初始值的计算, 如果list没有元素 即stream为null 则直接返回初始值
    int totalAge1 = ages.stream().reduce(0,(sum,age) -> sum+age);
    List<Integer> initList = Lists.newArrayList();
    int initTotalAge = initList.stream().reduce(0,(sum,age) -> sum+age);

    System.out.println("totalAge1: "+ totalAge1 + " initTotalAge: " + initTotalAge);
}

结果:
21
totalAge1: 21 initTotalAge: 0

8.collect方法以集合中的元素为基础,生成新的对象

在实际中,我们经常会以集合中的元素为基础,取其中的数据,来生成新的结果集,例如 按照过滤条件,返回新的List
或者将集合转化为 Set 或Map等操作,通过collect方法实现是十分简便的:

@Test
public void test10(){
    List<Person> list = getPersonList();
    //排序过滤等一系列操作之后的元素 放入新的list
    List<Person> filterList = list.stream().filter(e -> e.getAge() >20).collect(Collectors.toList());
    filterList.forEach(e -> System.out.println(e.toString()));

    //将 name 属性用" , ",连接拼接成一个字符串
    String nameStr = list.stream().map(Person::getName).collect(Collectors.joining(","));
    System.out.println(nameStr);
    //将name 放入到新的 set 集合中
    Set<String> nameSet = list.stream().map(person -> person.getName()).collect(Collectors.toSet());
    nameSet.forEach(e -> System.out.print(e + ","));

    System.out.println();
    System.out.println("map--------");
    Map<String,Person> personMap = list.stream().collect(Collectors.toMap(Person::getName,person -> person));
    personMap.forEach((key,val) -> System.out.println(key + ":" + val.toString()));
}

结果:
Person(name=liu, age=22, sex=male)
Person(name=zhao, age=21, sex=male)
Person(name=wang, age=21, sex=female)
liu,zhao,li,wang
wang,zhao,liu,li,
map--------
wang:Person(name=wang, age=21, sex=female)
zhao:Person(name=zhao, age=21, sex=male)
liu:Person(name=liu, age=22, sex=male)
li:Person(name=li, age=18, sex=female)

9.summaryStatistics 计算集合元素的最大、最小、平均等值

IntStream、LongStream 和 DoubleStream 等流的类中,有个非常有用的方法叫做 summaryStatistics(),可以返回 IntSummaryStatistics、LongSummaryStatistics 或者 DoubleSummaryStatistics,描述流中元素的各种摘要数据

 @Test
    public void test11(){
        List<Integer> ages = Arrays.asList(2,5,3,4,7);
        IntSummaryStatistics statistics = ages.stream().mapToInt(e -> e).summaryStatistics();
        System.out.println("最大值: " + statistics.getMax());
        System.out.println("最小值: " + statistics.getMin());
        System.out.println("平均值: " + statistics.getAverage());
        System.out.println("总和: " + statistics.getSum());
        System.out.println("个数: " + statistics.getCount());
    }
    结果:
    最大值: 7
    最小值: 2
    平均值: 4.2
    总和: 21
    个数: 5

原文链接:https://blog.csdn.net/qq_37176126/article/details/81273195

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容