Java 8 引入的新特性——Lambda 表达式,结合 forEach 方法可以更方便地实现遍历,相比传统的循环用起来Lambda 的函数式编程更加简洁,能减少不少冗余的代码行数,不过Lambda 表达式读起来会比较生涩,不过熟悉使用时真的香!
常用的场景有很多,下面只讨论Lambda 表达式对集合的相关操作。
先定义一些基础类,用lombok的@Data注解省去get和set这些方法:
import lombok.Data;
/**
* Person实体类
*/
@Data
public class Person {
private String name;
private Integer age;
private Double height;
private String email;
private Address address;
public Person() {
}
public Person(String name, Integer age, Double height, String email) {
this.name = name;
this.age = age;
this.height = height;
this.email = email;
this.address = new Address();
}
}
import lombok.Data;
/**
* 地址实体类
*/
@Data
public class Address implements Comparable{
private Integer id;
private String country;
private String province;
private String city;
/**
* 重写compareTo方法,根据id排序
* @param o
* @return
*/
@Override
public int compareTo(Address o) {
return this.getId().compareTo(o.getId());
}
// /**
// * 重写compareTo方法,根据country排序
// * @param o
// * @return
// */
// @Override
// public int compareTo(Address o) {
// return this.getCountry().compareTo(o.getCountry());
// }
}
下面就开始用Lambda 表达式对集合进行相关操作吧!上代码:
import com.google.common.collect.Lists;
import java.util.*;
import java.util.stream.Collectors;
/**
* 常见的lambda操作集合
*/
public class Lambda {
public static void main(String[] args) {
Person p1 = new Person("张三",20, 166.0, "[email protected]");
Person p2 = new Person("李四",60, 167.0, "[email protected]");
Person p3 = new Person("王五",15, 168.0, "[email protected]");
Person p4 = new Person("刘六",50, 168.0, null);
Person p5 = new Person("白七",30, 175.0, "[email protected]");
Person p6 = new Person("黄八",40, 168.0, null);
Person p7 = new Person("赵九",50, 186.0, "[email protected]");
Person p8 = new Person("赵九",50, 186.0, "[email protected]");
/** 使用google的collect.Lists工具类创建List更方便,不嫌麻烦也可以一个一个的 add 添加*/
List list = Lists.newArrayList(p1, p2, p3, p4, p5, p6, p7, p8);
/**
* 1.forEach()进行遍历集合
*/
list.forEach(item->{
//{ }这个就是循环体内的方法区
item.setAge(item.getAge() + 1);
System.out.println("名称:" + item.getName() + "年龄:" + item.getAge());
});
/**
* 2.stream()流操作
* 注:list集合为null时,list.stream()会抛NPE异常,可用 (List)Optional.ofNullable(source).orElse(Lists.newArrayListWithCapacity(0)) 将集合由null转为空集合。
*/
//2.1. 去重 distinct() 去重;collect(Collectors.toList())。封装成集合
List distinctList = list.stream().distinct().collect(Collectors.toList());
System.out.println("去重:" + distinctList);
//2.2 过滤 , filter(item->{}) item为每一项。 按照自己的需求来筛选list中的数据
List filterList = list.stream().filter(item->item.getAge()>3).collect(Collectors.toList());
System.out.println("过滤:" + filterList);
//2.3.1 map(), 提取对象中的某一元素 推荐使用 :: 实例上的实例方法引用
List mapList = list.stream().map(Person::getName).collect(Collectors.toList());
System.out.println("提取对象中的某一元素:" + mapList);
//2.3.2 提取对象中的元素转map(key:operateId value:operateName) (x, y) -> x 代表map的key的覆盖 p -> p 代表取整一个对象
Map mapList2 = list.stream().collect(Collectors.toMap(Person::getName, Person::getAge, (x, y) -> x));
Map mapList3 = list.stream().collect(Collectors.toMap(Person::getName, p -> p , (x, y) -> x));
System.out.println("提取对象中的元素成为map:" + mapList2);
//2.4 Stream中的高阶函数 sum(),max(),min(),average()
double sum = list.stream().mapToDouble(Person::getAge).sum();
System.out.println("统计sum函数:" + sum);
//2.5.1 分组 Collectors.groupingBy(属性名)
Map> map = list.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println("分组:" + map);
//2.5.2 多重分组 Collectors.groupingBy(属性,Collectors.groupingBy(属性))
Map>> map2 = list.stream().collect(Collectors.groupingBy(Person::getName,Collectors.groupingBy(Person::getAge)));
System.out.println("多重分组:" + map2);
//2.5.3 分组并计算综合 计算最大值、最小值、平均值、求和、计数统计 对应的摘要统计的功能类 IntSummaryStatistics、LongSummaryStatistics 和 DoubleSummaryStatistics
IntSummaryStatistics intSummaryStatistics = list.stream().mapToInt(Person::getAge).summaryStatistics();
int max = intSummaryStatistics.getMax();
System.out.println("计算最大值:" + max);
Map> map3 = list.stream().collect(Collectors.groupingBy(Person::getName,Collectors.groupingBy(Person::getAge,Collectors.summarizingInt(Person::getAge))));
System.out.println("分组并计算综合:" + map3);
//2.6.1 排序 sorted((第一个对象,第二个对象)->返回值)
List sortedList = list.stream().sorted((o1,o2)->o1.getAge()-o2.getAge()).collect(Collectors.toList());
System.out.println("排序:" + sortedList);
//2.6.2 Comparator排序 可以使用thenComparing多重排序(注:comparing和thenComparing都会抛NPE,如下例子,当age有null值时会抛NPE,当name相邻有null时会抛NPE,不相邻则不会)
List sortedList2 = list.stream().sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getName)).collect(Collectors.toList());
System.out.println("Comparator排序:" + sortedList2);
//2.6.3 Comparator自定义排序 实现Comparable并重写compareTo方法
list.forEach(item->item.getAddress().setId(item.getAge()));
List sortedList3 = list.stream().sorted(Comparator.comparing(Person::getAddress)).collect(Collectors.toList());
System.out.println("Comparator自定义排序:" + sortedList3);
//2.6.4 Comparator nullsFirst||nullsLast排序 对字段为null时的排序,将null的排在最前or最后,这里主要thenComparing的原始除了相邻null会抛NPE,email和height同时为null也会抛NPE
List sortedList4 = list.stream().sorted(Comparator.comparing(Person::getEmail, Comparator.nullsLast(String::compareTo)).thenComparing(Person::getHeight)).collect(Collectors.toList());
System.out.println("Comparator nullsLast排序:" + sortedList4);
}
}