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<Address>{
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<Person> 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<Person> distinctList = list.stream().distinct().collect(Collectors.toList());
System.out.println("去重:" + distinctList);
//2.2 過濾 , filter(item->{}) item爲每一項。 按照自己的需求來篩選list中的數據
List<Person> filterList = list.stream().filter(item->item.getAge()>3).collect(Collectors.toList());
System.out.println("過濾:" + filterList);
//2.3.1 map(), 提取對象中的某一元素 推薦使用 :: 實例上的實例方法引用
List<String> 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<String, Integer> mapList2 = list.stream().collect(Collectors.toMap(Person::getName, Person::getAge, (x, y) -> x));
Map<String, Person> 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<Integer, List<Person>> map = list.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println("分組:" + map);
//2.5.2 多重分組 Collectors.groupingBy(屬性,Collectors.groupingBy(屬性))
Map<String, Map<Integer, List<Person>>> 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<String, Map<Integer, IntSummaryStatistics>> 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<Person> 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<Person> 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<Person> 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<Person> sortedList4 = list.stream().sorted(Comparator.comparing(Person::getEmail, Comparator.nullsLast(String::compareTo)).thenComparing(Person::getHeight)).collect(Collectors.toList());
System.out.println("Comparator nullsLast排序:" + sortedList4);
}
}