/**
* 符合lambda表达式的接口也叫函数式接口:
* 除了默认方法和Object类的方法外,只有一个抽象方法的接口才能符合lambda表达式的要求
* 可以使用@FunctionalInterface来校验,如果没报错就是符合要求的
*
*
*/
@FunctionalInterface
public interface Animal { default String getName(){
return "animal";
} void eat(); }
//无参有返回
public interface Person {
String getName();
}
//有参无返回
public interface Sckool { void learn(String name);
}
//有参有返回
public interface Student {
String conCat(String str,String str2);
}
package lambda; public class testLambda {
public static void main(String[] args) {
//要调用一个接口的方法,要么定义一个类来实现该接口,要么使用匿名内部类:
//下面使用匿名内部类: eat(new Animal() {
@Override
public void eat() {
System.out.println("动物吃东西");
}
});
/**
* 如果匿名内部类只有一个方法,可以使用lambda表达式替换:
* 总共分下面4种情况:
* 无参无返回格式:
* 单条语句时()->xxx ;多条语句时()->{xx;aa;}
* 无参有返回:
* 单条语句时()->xxx;多条语句时()->{xx; return aa;}
* 有参无返回:
* 单条语句单个参数时:a->xxx;多条语句单个参数时a->{xx;cc;}
* 单条语句多个参数时:(a,b)->xxx;多条语句多个参数时(a,b)->{xx;cc;}
*
* 有参有返回:
* 单条语句单个参数时:a->xxx;多条语句单个参数时a->{xx;return cc;}
* 单条语句多个参数时:(a,b)->xxx;多条语句多个参数时(a,b)->{xx; return cc;}
*/ //-------- 无参无返回格式:
//单条语句时()->xxx
eat(()-> System.out.println("aaa")); //多条语句时()->{xx;aa;}
eat(()->{
System.out.println("dd");
System.out.println("cc");
}); //---------无参数有返回格式:
// 单条语句时()->xxx;
String name=getName(()->"kk"); //多条语句时()->{xx; return aa;}
getName(()->{
System.out.println("dd");
return "cc";
}); //--------有参数无返回时 //单条语句单个参数时
learn(a-> System.out.println(a)); //多条语句单个参数时a->{xx;cc;}
learn(a->{
System.out.println("lll");
System.out.println("cc");
}); //单条语句多个参数时
// learn((a,b)-> System.out.println(a+b)); //多条语句多个参数时(a,b)->{xx;cc;}
/**
*
* learn((a,b)-> {
System.out.println("lll");
System.out.println("cc");
}); *
*/ //---------有参数有返回 //单条语句单个参数时:a->xxx;
// learn(a-> "dd"); //多条语句单个参数时a->{xx;return cc;}
/**
* learn(a->{
System.out.println("lll");
return "ss";
});
*
*
*/ //单条语句多个参数时:(a,b)->xxx
String subject=concat((a,b)->a+b); //多条语句多个参数时(a,b)->{xx; return cc;}
String subject2=concat((a,b)->{
System.out.println("ddd");
return a+b;
}); /**
*
* 我们使用lambda表达式时候,都是要实现一个方法,如果你要实现的方法刚好其他类有,那么就可以引用其他类的方法过来当做该匿名内部类的实现
* 所以方法的引用分为:
* 静态方法的引用,如System.out:println
* 非静态方法的引用:如 new Dog()::eat;
* 参数类型方法的引用,例如一个要实现的方法参数是String a,String b ,期望的结果是a+b,那么可以引用String::concat方法
*
*
*/ learn(System.out::print); //刚好learn的内部类要实现的方法跟System.out的方法长得一样,所以可以引用该方法当做自己的实现方法
eat(new testLambda()::haveMeal);//非静态方法的引用
String str=concat(String::concat);//参数
System.out.println(str); } public static void eat(Animal animal){
animal.eat();
}
public static String getName(Person person){
return person.getName();
}
public static void learn(Sckool sckool){
sckool.learn("java");
}
public static String concat(Student student){
return student.conCat("java","php");
} public void haveMeal(){
System.out.println("吃饭");
}
}

//stream 流:

package lambda;

import java.math.BigDecimal;

public class Cat {
private String name;
private BigDecimal price; public Cat(String name, BigDecimal price) {
this.name = name;
this.price = price;
} @Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", price=" + price +
'}';
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public BigDecimal getPrice() {
return price;
} public void setPrice(BigDecimal price) {
this.price = price;
}
}
package lambda; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class testLambda {
public static void main(String[] args) {
List<Cat> list=new ArrayList<>();
list.add(new Cat("k",new BigDecimal("200")));
list.add(new Cat("g",new BigDecimal("100")));
list.add(new Cat("k",new BigDecimal("300")));
list.add(new Cat("l",new BigDecimal("400")));
list.add(new Cat("b",new BigDecimal("500")));
list.add(new Cat("b",new BigDecimal("501")));
/**
* Stream流:跟IO的流是不一样的,比较适当的比喻可以当做一个管道,数据从管道一端流经另一端,中间会经过多个操作,如过滤,排序
*
* 流程: 源 ------过滤----排序---终止-结果
*
* 所有操作分为三类
* 1.创建流
* 2.中间操作(惰性操作) : 凡是返回值类型是Stream的都是中间操作,如果只有中间操作,没有终止操作,流是不会执行的
* 3.终值操作
*
*
*
* 创建:
* Collection.stream();
* Arrays.asList("a","b").stream();
* Stream.of("a","b");
*
*/ /**
* 流的特点:
* 1.不能重复使用,每经过一个中间操作都返回新的流,之前的流就关闭了
* 2.最多只能有一个终值操作,并且终值操作都是在最后
* 3.执行顺序:
* 假如一个流经过 filter--sorted操作,顺序是一个元素先经过filter--sorted 然后下一个元素经过filter--sorted,并不是所有元素先经过filter,然后经过sorted
*
*
*/
Stream<Cat> stream = list.stream();
//过滤操作是中间操作,如果没有终值操作就不会执行
Stream<Cat> stream2 = stream.filter(a -> {
System.out.println("中间操作是惰性的,这句话不会输出");
return a.getName().equals("b");
});
//下面的操作会报错:java.lang.IllegalStateException: stream has already been operated upon or closed
//因为stream在上一步执行完filter就关闭了
/*stream.filter(a-> {
System.out.println("流不能重复使用");
return a.getName().equals("b");
}).toArray();*/ Object[] bs = stream2.filter(a -> {
System.out.println("有终值操作toArray,所以该方法会被执行");
return a.getName().equals("b");
}).toArray(); //测试流是一个一个执行元素还是全部一起执行 list.stream().filter(a->{
System.out.println("过滤操作");
return !a.getName().equals("oo");
}).forEach(a-> System.out.println("遍历操作")); //输出结果: 过滤操作 遍历操作 过滤操作 遍历操作 ..... //常用的Strem API //过滤filter:上面的例子
System.out.println(Arrays.toString(bs)); //peek 和 forEach操作,peek不是终值操作,执行后还能继续执行其他中间操作,forEach是终值操作 list.stream().peek(System.out::println); //不会打印数据,因为中间操作是懒惰的
list.stream().peek(System.out::println).toArray();
list.stream().forEach(System.out::println);//终值操作,直接会输出结果 //map 将元素按照一定规则映射成另外一个元素
List<String> nameList = list.stream().map(a -> a.getName()).collect(Collectors.toList());
System.out.println(nameList); //distinct 去重
List<String> distionctNameList = list.stream().map(a -> a.getName()).distinct().collect(Collectors.toList());
System.out.println(distionctNameList); //sorted 排序
List<Cat> sortList = list.stream().sorted((a, b) -> b.getPrice().compareTo(a.getPrice())).collect(Collectors.toList());
System.out.println(sortList);
//limit 操作
List<Cat> limitList = list.stream().limit(2).collect(Collectors.toList());
System.out.println(limitList); //mapToInt和reuduce用户sum()操作时,调用int reduce(int identity, IntBinaryOperator op);所有元素op操作后加上identity的值就得到sum()的值了 int reduce = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(0, (a, b) -> a + b); //2001
int reduce2 = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(-1, (a, b) -> a + b);//2000
int reduce3 = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(20, (a, b) -> a + b);//2021
System.out.println(reduce);
System.out.println(reduce2);
System.out.println(reduce3);
     //BigDecimal payAmount = billMastList.stream().map(a -> a.getAmtBillPayment()).reduce(BigDecimal.ZERO, BigDecimal::add); 金额处理 //skip操作 跳过多少个元素,从1开始算
List<Cat> skipList = list.stream().skip(1).collect(Collectors.toList());
System.out.println(skipList);
//价格最贵的 max(Comparator<? super T> comparator)
Cat cat = list.stream().max((a, b) -> a.getPrice().compareTo(b.getPrice())).get();
System.out.println(cat); // boolean anyMatch(Predicate<? super T> predicate),判断是否有比600价格贵的
boolean b = list.stream().allMatch(a -> a.getPrice().compareTo(new BigDecimal(600)) > 0);
boolean b2 = list.stream().anyMatch(a -> a.getPrice().compareTo(new BigDecimal(500)) > 0);
System.out.println(b);
System.out.println(b2);
//findAny() 获取任意一个
Cat cat1 = list.stream().findAny().get();
System.out.println(cat1); //findFirst() 获取第一个
Cat cat2 = list.stream().findFirst().get();
System.out.println(cat2);
//flatMap:比较像降维打击,如三维空间变成二维空间,具体的意思是每个元素经过处理,生成新的流.例如这里每个cat获取它的名字组成一个新的集合
//再举个例子,订单跟商品,一个订单集合经过flatMap,获取每个订单的商品集合组成一个新的流
List<String> flatMapList = list.stream().flatMap(a -> Stream.of(a.getName())).collect(Collectors.toList());
System.out.println(flatMapList);
    
       //list转map 第一个参数是key值,第二个参数value值,第三个参数是key重复时,value如何进行合并
Map<String, BigDecimal> map = list.stream().collect(Collectors.toMap(a -> a.getName(), a -> a.getPrice(),(c, d)->c.add(d)));
System.out.println(map);

//分组功能
List<PerSon> list=new ArrayList<>();
list.add(new PerSon("yang",12));
list.add(new PerSon("yang",20));
list.add(new PerSon("ming",12));
list.add(new PerSon("ming",362));
list.add(new PerSon("tt",12));
list.add(new PerSon("kk",12));
Map<String, List<PerSon>> collect = list.stream().collect(Collectors.groupingBy(PerSon::getName)); //会分成四组,根据名字来分组

//注意 list转map如果value值为null会报,如果key重复,不处理也会报错,处理最好如下所示
custmerNameMap = customerInfoBatchList.stream().filter(a->StringUtils.isNotBlank(a.getCustomerName())) //过滤空值

.collect(Collectors.toMap(XfaceCustomerInfoListForBatchResponseSubDTO::getCustomerId, XfaceCustomerInfoListForBatchResponseSubDTO::getCustomerName,(k1,k2)->k1)); //
(k1,k2)->k1)代表key重复时,取第一个


//总结:所有API都不用记!!要用任何一个方法,点开Stream类可以查看到,或者idea工具提示可以找到任何一个方法,每个方法的参数都是一个接口,找到该接口看看其要实现的方法,然后使用lambda表达式就可以了  } }

idea安装插件可以对stream流进行debug:

lamda表达式与Stream 流操作,reduce,flatMap,groupingBy等的更多相关文章

  1. java8 stream流操作的flatMap(流的扁平化)

    https://mp.weixin.qq.com/s/7Fqb6tAucrl8UmyiY78AXg https://blog.csdn.net/Mark_Chao/article/details/80 ...

  2. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

  3. 超强的Lambda Stream流操作

    原文:https://www.cnblogs.com/niumoo/p/11880172.html 在使用 Stream 流操作之前你应该先了解 Lambda 相关知识,如果还不了解,可以参考之前文章 ...

  4. 全面吃透JAVA Stream流操作,让代码更加的优雅

    全面吃透JAVA Stream流操作,让代码更加的优雅 在JAVA中,涉及到对数组.Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行 ...

  5. 深度掌握 Java Stream 流操作,让你的代码高出一个逼格!

    概念 Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选.排序.聚合等. Stream 的操作符大体上分为两种:中间操作符和终止操作符 中 ...

  6. Node学习笔记(一):stream流操作

    NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...

  7. Stream 流操作

     Stream 类 先看下面的图 Stream 是所有流的抽象基类(不能被实例化,需要使用他的派生类FileStream/MemoryStream/BufferedStream).流是字节序列的抽象概 ...

  8. stream流操作List工具类

    工作中操作List对于程序猿来说是"基本操作",为了更加便利,对JDK8的新特性stream流进行二次封装.话不多说,直接上代码 package com.mydemo; impor ...

  9. .net System.IO.Stream 流操作类(FileStream等)

    Stream 是所有流的抽象基类.流是字节序列的抽象概念. 流涉及到的3个基本操作: 读取流,读取是指从流到数据结构(如字节数组)的数据传输. 写入流,写入是指从数据结构到流的数据传输. 流查找,查找 ...

随机推荐

  1. 传统servelt项目之分页操作

    需求说明: • 演示最终分页效果 • 提供分页素材     • 分页的作用 • 数据量大,一页容不下 • 后台查询部分数据而不是全部数据 • 降低带宽使用,提高访问速度     • 分页的实现思路 • ...

  2. vue组件获取和vue-cli的基本了解

    Vue获取组件的一些方法 this.$refs.xxx 给标签绑定ref属性,获取的是当前DOM对象 给组件绑定ref属性,获取的是组件实例对象 this.$parent 获取当前组件的父组件,为一个 ...

  3. k8s部署mysql主从复制

    Mysql主从 准备环境 一,准备软件 官方docker_image :Mysql5.7.28 Docker Version:        19.03.4 K8s api-version:      ...

  4. 无法登陆网站,nginx漏配置

    location / {         try_files $uri $uri/ /index.php?$query_string; }   这条主要是将index.php入口文件重写掉,所以平常我 ...

  5. 利用 Python 写个七夕表白神器

    今天是七夕节,相比于现代人自创的 502,不对是 520,七夕才是中国传统意义上的情人节,本文分享几个 Python 表白程序,情侣可以现学现用,单身的话也可以先收藏一下,说不定下次就用上了. 很多人 ...

  6. Lct 动态链接树

    通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...

  7. 手写mybatis框架

    前言 很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践. 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 .整个代码都是自 ...

  8. 深入了解Redis【一】源码下载与参考资料准备

    引言 一直在使用redis,但是却没有系统的了解过它的底层实现,准备边学习边记录,深入了解redis. 打算分析以下几个方面: redis的基本类型及底层原理与java对比,每种数据类型的使用场景 r ...

  9. Azure Blob (三)参数设置说明

    一,引言 上一篇将 Azure Blob 存储的时候,有使用到一个 .NET  Core Web 项目,通过代码的方式进行操作 Azure Blob 的数据,接着上一篇的内容,今天继续看一下代码,具体 ...

  10. oracle之数据限定与排序

    数据限定与排序 6.1 简单查询语句执行顺序 from, where, group by, having, order by, select where限定from后面的表或视图,限定的选项只能是表的 ...