一.lambda 表达式
lambda 表达式 是 java jdk 1.8的新特性,面向函数编程,它简化了编码.让代码变得简单优雅.(但个人觉得 这个有点骚气) 高大上的感觉.
1.它的使用规则
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)
通用的规律是:
小括号指向大括号,小括号里面放参数,大括号里面写代码。
举个例子:
(Integer n1,Integer n2) -> n1 + n2
这个就相当于
Integer method(Integer n1, Integer n2) {
return n1 + n2;
}
常用场景:
列表迭代:
List list= Arrays.asList(1, 2, 3, 4, 5);
list.forEach(x -> System.out.println(x));
线程:
new Thread (() -> System.out.println(“线程开启!”)).start()
二.Stream Api
1.概述
Java 8 引入的一个重要的特性无疑是 Stream API。Stream 翻译过来是“流”,突然想到的是大数据处理有个流式计算的概念,数据通过管道经过一个个处理器(Handler)进行筛选,聚合,而且流都具有向量性,强调的是对数据的计算处理,而集合强调的是数据集。Stream可以看做是一个可操作的数据集序列,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。有点类似于数据库中的增删改查操作。十分高效而且易于使用。
它的特点
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
中间可使用的操作
筛选与切片:
filter——接收 Lambda , 从流中排除某些元素。
limit——截断流,使其元素不超过给定数量。
skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
查找与匹配:
allMatch–检查是否匹配所有元素
anyMatch–检查是否至少匹配一个元素
noneMatch–检查是否没有匹配所有元素
findFirst–返回第一个元素
findAny–返回当前流中的任意元素
count–返回流中元素的总个数
max–返回流中最大值
min–返回流中最小值
归约:
reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
——可以将流中元素反复结合起来,得到一个值。
最终汇聚 collect
collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
1、collect在流中生成列表,map,等常用的数据结构
2、toList()
3、toSet()
4、toMap()
collect是基于Collectors实现的,而Collectors除了上面的to…之外还有
maxBy:最大
minBy:最小
summingDouble:求和
averagingDouble:平均值
counting:计数
summarizingDouble:统计,上面5种都包括
groupingBy:分组(可以自定义分组,可以多级分组)
partitioningBy:分区,将满足条件的分成一个区,不满足的分成一个区
joining:连接字符串,delimiter:分割符,prefix:前缀,suffix:后缀
reducing:归约
Sreeam Api 的使用 需要结合lambda 表达式 ,所以 学习stream api 之前 需要对了lambda 表达式有一定的了解.
groupingBy 分组
public static void main(String[] args) {
// 根据市场类型 查询 出所有的股票代码 数据
List<EtfStockNote> stocks = getDimAllConstituentStocks(DimEtfIopvQuery.getDimEtfFoundCodeByMarkType("102"));
// 这里面 一个基金有多个成分股,所以 想构造出 key 是 基金, 使用一个集合装成分股信息
Map<String, List<EtfStockNote>> listMap = stocks.stream().collect(Collectors.groupingBy(EtfStockNote::getFundCode));
for (Map.Entry<String, List<EtfStockNote>> entry : listMap.entrySet()) {
System.out.println(entry);
}
}
2.用法
举个例子:
public static void test() {
// 需求是 我要从这list中找出 是会员的地址 且用户积分最高前三位 然后 只需要用户电话和地址.
ArrayList<User> list = new ArrayList<>();
list.add(new User(2000, "北京朝阳", "18601980988", true));
list.add(new User(599, "北京海淀", "135019809122", false));
list.add(new User(660, "杭州西湖", "18501980988", true));
list.add(new User(1200, "杭州滨江", "13701980933", true));
list.add(new User(150, "北京昌平", "152019809789", true));
list.add(new User(980, "杭州上城", "152019809782", true));
list.add(new User(980, "北京大兴", "152019809679", true));
// 这个就是从集合list形成流 然后过滤是会员的 排序根据用户积分 然后去前三位 之后只取出 用户的电话和地址
Map<String, String> collect = list.stream().filter(k -> k.getMembers()).
sorted((t1, t2) -> t2.getIntegral() - t1.getIntegral()).limit(3).
collect(Collectors.toMap(User::getPhoneNum, User::getAddr, (k1, k2) -> k2));
//这里解释一下 (k1, k2) -> k2) 这个的意思如果key 相同时 是去前一个还是后一个,这里取得是后一个key
// 为了能一步步分析 我这边先做个拆解
// 把 list 转换为 stream 流
Stream<User> stream = list.stream();
// 这里的过滤写法和形式有好几种 可根据需要来
//1.要过滤是会员 的
// k.getMembers() 这个 K 就是个参数 随便定义 他代表的就是 User 对象
// k.getMembers() 的意思获取会员 得到一个布尔值 true/flase
stream.filter(k->k.getMembers())
// 2. 要 获取用户地址 是北京的
stream.filter(k->{
if(k.getAddr().contains("北京")){
}
}).collect() // if 写要处理的逻辑 然后再转成需要的集合
// 下边的分析就简单了
//获取会员然后排序 limit 是取值
stream.filter(k->k.getMembers()).sorted((t1, t2) -> t2.getIntegral() - t1.getIntegral())
// 这里 是遍历对象 获取什么值做key 什么做 value
//讲下这个 :: 这两个是对含有user 集合遍历取值
collect(Collectors.toMap(User::getPhoneNum, User::getAddr, (k1, k2) -> k2));
}
public class UserEntity implements Serializable {
private Integer id;
private String userName;
private String phone;
}
public static void main(string args[]){
List<UserEntity> users=new ArrayList<>();
users.add(new UserEntity(1,"张三","18399990000"));
users.add(new UserEntity(2,"王五","18399990023"));
users.add(new UserEntity(3,"里斯","18399990005"));
// 获取list中所有对象的某个属性
List<String> courseIds= users.stream().map(UserEntity::getUserName).collect(Collectors.toList());
}
通过以上可以了解到 它的大致用法 ,其实 list set map 都是同理.
并发
1、stream替换成parallelStream或 parallel
2、输入流的大小并不是决定并行化是否会带来速度提升的唯一因素,性能还会受到编写代码的方式和核的数量的影响
3、影响性能的五要素是:数据大小、源数据结构、值是否装箱、可用的CPU核数量,以及处理每个元素所花的时间
Optional 的用法
1、Optional 是为核心类库新设计的一个数据类型,用来替换 null 值。
2、人们对原有的 null 值有很多抱怨,甚至连发明这一概念的Tony Hoare也是如此,他曾说这是自己的一个“价值连城的错误”
3、用处很广,不光在lambda中,哪都能用
4、Optional.of(T),T为非空,否则初始化报错
5、Optional.ofNullable(T),T为任意,可以为空
6、isPresent(),相当于 !=null
7、ifPresent(T), T可以是一段lambda表达式 ,或者其他代码,非空则执行
//对 optional 的用法使用
public static void test() {
User u = null;
User user = new User(007, "北京", "18601998088", true);
// 你可以使用 of() 和 ofNullable() 方法创建包含值的 Optional。
// 两个方法的不同之处在于如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException:
// Optional<User> u1 = Optional.of(u);
// System.out.println(u1); // 会报错 空指针异常
Optional<User> u2 = Optional.ofNullable(u);
System.out.println(u2); // 这个 传入为null 不会报错 会输出 Optional.empty
//所以不确定传入的值是否为null 则 选择ofNullable 来创建Optional 实例
//返回默认值 orElse 的用法
User uu = null;
User uuser = new User(007, "北京", "18601998088", true);
// 这里 uu 对象是空的,所以返回了作为默认值的 uuser。
User result = Optional.ofNullable(user).orElse(uuser);
System.out.println(result); // 这里会输出 默认值 也就是 uuser 的值
// 如果对象的初始值不是 null,那么默认值会被忽略:
User user2 = new User(007, "北京", "18601998088", false);
User user3 = new User(007, "北京", "18601998088", true);
User orElse = Optional.ofNullable(user2).orElse(user3);
System.out.println(orElse);// 这里因为 user2 不为null 所以默认值不会输出
//orElse() 和 orElseGet() 的不同之处
User user = new User("john@gmail.com", "1234");
logger.info("Using orElse");
User result = Optional.ofNullable(user).orElse(createNewUser());
logger.info("Using orElseGet");
User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
/**
* 结论: 当对象为空而返回默认对象时,行为并无差异
* 当两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。
* 不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象
*/
// 转换值
//map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中。
// 这就使对返回值进行链试调用的操作成为可能 ——
//这里的下一环就是 orElse()。
User user4 = new User(007, "北京", "18601998088", true);
String s = Optional.ofNullable(user4).map(o -> o.getAddr()).orElse("地址不详");
//过滤 filter
Optional<User> userOptional = Optional.ofNullable(user4).filter(u -> u.getAddr().
contains("北京"));