構建一個User實體類供演示
public class Users { /** * ID */ private Long id; /** * 用戶名 */ private String name; /** * 年齡 */ private int age; /** * 工號 */ private String jobNumber; /** * 性別 */ private String sex; /** * 註冊時間 */ private Date entryDate; /** * 成員組織 */ private BigDecimal familyMemberQuantity; private Long userId; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getJobNumber() { return jobNumber; } public void setJobNumber(String jobNumber) { this.jobNumber = jobNumber; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getEntryDate() { return entryDate; } public void setEntryDate(Date entryDate) { this.entryDate = entryDate; } public BigDecimal getFamilyMemberQuantity() { return familyMemberQuantity; } public void setFamilyMemberQuantity(BigDecimal familyMemberQuantity) { this.familyMemberQuantity = familyMemberQuantity; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } @Override public String toString() { return "Users{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", jobNumber='" + jobNumber + '\'' + ", sex='" + sex + '\'' + ", entryDate=" + DateFormatUtils.format(entryDate, "yyyy-MM-dd HH:mm:ss") + ", familyMemberQuantity=" + familyMemberQuantity + '}'; } }
一、根據字段分組得到多個List集合
構建一個產生Users的靜態法
/** * 生產虛擬用戶 * * @return */ public static List<Users> produceUser() { List<Users> usersList = new ArrayList<>(); for (int i = 1; i <= 10; i++) { Users users = new Users(); users.setId(Long.valueOf(i)); users.setName("kobe" + i); users.setAge(15 + new Random().nextInt(5)); users.setJobNumber("jobNumber" + i); if (i % 2 == 0) { users.setSex("男"); } else { users.setSex("女"); } users.setEntryDate(new Date()); users.setFamilyMemberQuantity(new BigDecimal(i)); usersList.add(users); } return usersList; }
利用Java8 特性,根據對象的某個屬性進行分組
@Test public void groupByGender() { List<Users> list = produceUser(); // 根據性別進行分組 Map<String, List<Users>> collect = list.stream().collect(Collectors.groupingBy(Users::getSex)); Set<Map.Entry<String, List<Users>>> entries = collect.entrySet(); entries.forEach(item -> { // 性別 男 / 女 String gender = item.getKey(); // 男集合 / 女集合 List<Users> usersList = item.getValue(); System.out.println(gender); usersList.forEach(user -> System.out.println(user)); }); }
輸出結果如下
二、集合求和
2.1 根據對象中的某個字段求和
/** * 根據年齡字段求總和 */ @Test public void getSumByStream() { List<Users> list = produceUser(); int sum = list.stream().mapToInt(Users::getAge).sum(); System.out.println("共計:" + list.size() + "個用戶,所有年齡總和爲:" + sum); // 求最大年齡 Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get(); System.out.println(integer); // 得到最大年齡對象 Users users = list.stream().max(Comparator.comparingInt(Users::getAge)).get(); System.out.println(users); // 求平均年齡 System.out.println(list.stream().mapToInt(Users::getAge).average().getAsDouble()); // 求最大年齡 System.out.println(list.stream().mapToInt(Users::getAge).max().getAsInt()); }
輸出結果如下
2.2 List<數值型> 求和
/** * 根據List求和 */ @Test public void getListSumByJava8() { List<Integer> listInt = new ArrayList(); List<Double> listDoub = new ArrayList(); for (int i = 0; i < 500; i++) { listInt.add(new Random().nextInt(1000)); listDoub.add(new Random().nextDouble()); } System.out.println("=======數值型Integer求和======"); Integer integer = listInt.stream().reduce(Integer::sum).orElse(0); System.out.println(integer); System.out.println("=======數值型Double求和======"); Double integer1 = listDoub.stream().reduce(Double::sum).orElse(0.00); System.out.println(integer1); // 取最大值 System.out.println(listInt.stream().reduce(Integer::max).orElse(0)); System.out.println(listInt.stream().mapToInt(Integer::valueOf).max().getAsInt()); // 取最小值 System.out.println(listInt.stream().reduce(Integer::min).orElse(0)); // 取平均值 System.out.println(listInt.stream().mapToInt(Integer::valueOf).average().getAsDouble()); }
輸出結果如下
三、遍歷List集合
/** * 遍歷對象 */ @Test public void traverseByJava8(){ List<Users> list = produceUser(); list.forEach(System.out::println); }
輸出結果如下
四、過濾List集合
/** * 過濾對象 */ @Test public void filterByJava8() { List<Users> list = produceUser(); System.out.println("原始數據爲:"); System.out.println("==============過濾後的數據爲==============="); list.forEach(System.out::println); //篩選出年齡大於3歲小於8歲的對象 List<Users> collect = list.stream().filter(s -> s.getAge() > 13 && s.getAge() < 18).collect(Collectors.toList()); System.out.println("過濾結束後的數據爲:"); collect.forEach(System.out::println); }
輸出結果如下
五、獲取List中的最大最小值
5.1 根據特定需求中的某個字段求最大最小
/** * 求最大最小值,根據業務類型選擇合適的類型值 */ @Test public void maxOrMinByJava8() { List<Users> list = produceUser(); //根據mapTO**得到最大最小 ---寫法一 double asDouble = list.stream().mapToDouble(Users::getAge).max().getAsDouble(); System.out.println("將最大值轉換爲Double類型進行展示,最大爲:" + asDouble); double asDouble1 = list.stream().mapToDouble(Users::getAge).min().getAsDouble(); System.out.println("將最小值轉換爲Double類型進行展示,最小爲:" + asDouble1); int asInt = list.stream().mapToInt(Users::getAge).max().getAsInt(); System.out.println("將最大值轉換爲Int類型進行展示,最大爲:" + asInt); //根據map得到最大最小 ---寫法二(推薦) Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get(); System.out.println("將最大值轉換爲字段對應類型進行展示,最大爲:" + integer); Integer integer1 = list.stream().map(Users::getAge).min(Integer::compareTo).get(); System.out.println("將最小值轉換爲字段對應類型進行展示,最小爲:" + integer1); }
輸出結果如下
5.2 根據特定需求中的某個字段求平均值
/** * 求最大最小值,根據業務類型選擇合適的類型值 */ @Test public void avgByJava8() { List<Users> list = produceUser(); double avgAge = list.stream().mapToDouble(Users::getAge).average().getAsDouble(); System.out.println("平均年齡爲:" + avgAge); }
輸出結果如下
六、根據需求將List轉爲Map
/** * List -> Map * 需要注意的是: * toMap 如果集合對象有重複的key,會報錯Duplicate key .... * user1,user2的id都爲1。 * 可以用 (k1,k2)->k1 來設置,如果有重複的key,則保留key1,捨棄key2 */ @Test public void mapToListByJava8() { List<Users> list = produceUser(); Map<Long, Users> map = list.stream().collect(Collectors.toMap(Users::getId, a -> a, (k1, k2) -> k1)); for (Map.Entry<Long, Users> entry : map.entrySet()) { Long key = entry.getKey(); System.out.println("map中的key是:" + key); System.out.println("map中的value是:" + entry.getValue().toString()); } // 根據ID和年齡獲得map Map<Long, Integer> collect = list.stream().collect(Collectors.toMap(Users::getId, item -> Optional.ofNullable(item.getAge()).orElse(0) , (k1, k2) -> k1)); System.out.println(collect.toString()); }
輸出結果如下
七、List排序
/** * 排序(單字段/多字段排序) */ @Test public void sortByJava8() { List<Users> list = produceUser(); System.out.println("============未排序的數據============="); System.out.println(list.toString()); try { //單字段排序,根據名字排序 System.out.println("============單字段排序,根據名字排序============="); list.sort(Comparator.comparing(Users::getName)); System.out.println(list.toString()); //多字段排序,根據年齡再根據-->名字排序 System.out.println("============多字段排序,根據年齡再根據-->名字排序============="); list.sort(Comparator.comparing(Users::getAge, (o1, o2) -> o2 - o1).thenComparing(Users::getName)); System.out.println(list.toString()); } catch (Exception e) { e.printStackTrace(); } }
輸出結果如下
八、List去重
/** * 去重 */ @Test public void distinctByJava8() { List<String> numList = new ArrayList(); numList.add("kevin"); numList.add("kevin"); numList.add("kevin1"); numList.add("kevin2"); numList.add("kevin1"); numList.add("kevin2"); System.out.println("===========未去重的數據============"); System.out.println(numList.toString()); System.out.println("===========去重後的數據============"); List<String> collect = numList.stream().distinct().collect(Collectors.toList()); System.out.println(collect.toString()); }
輸出結果如下
九、List的合併
首先了解下交集並集差集的概念,分別有三個區域A,B,C
9.1 List的合併之—>並集
/** * 得到兩個集合的並集 */ @Test public void listByJava8() { List<String> list1 = new ArrayList(); list1.add("aaa"); list1.add("bbb"); list1.add("ccc"); list1.add("aaa1"); List<String> list2 = list1; list2.add("ddd"); list2.add("aaa"); list2.add("eee"); list2.add("ccc"); list2.add("fff"); list2.add("aaa1"); list2.add("aaa2"); //根據整個對象是否一致來去重合並得到並集 System.out.println("==========並集: 集合A{1, 2, 3} 和集合B {2, 3, 4} 的並集是 {1, 2, 3, 4}=========="); System.out.println("---->並集寫法一 [去重]"); System.out.println("============並集舉例一:根據List去重特性合併多個Lits============"); List<String> collect = Stream.of(list1, list2).flatMap(Collection::stream).distinct().collect(Collectors.toList()); System.out.println(collect.toString()); System.out.println("---->並集寫法二 "); System.out.println("============並集舉例二:根據List得到並集============"); List<String> collect1 = list1.stream().filter(s -> list2.contains(s)).distinct().collect(Collectors.toList()); System.out.println(collect1); System.out.println("==========交集: 集合A {1,2,3} 和集合B {2,3,4} 的交集爲 {2,3}。即{1,2,3}∩{2,3,4}={2,3}=========="); }
輸出結果如下
9.2 List的合併之—>交集(即兩個或多個list重複的元素的集合)
/** * 得到兩個集合的交集 */ @Test public void listBingByJava8() { System.out.println("==========交集: 集合A {1,2,3} 和集合B {2,3,4} 的交集爲 {2,3}。即{1,2,3}∩{2,3,4}={2,3}=========="); List<String> list1 = new ArrayList(); list1.add("aaa"); list1.add("bbb"); list1.add("ccc"); list1.add("aaa1"); List<String> list2 = list1; list2.add("ddd"); list2.add("aaa"); list2.add("eee"); list2.add("ccc"); list2.add("fff"); list2.add("aaa1"); list2.add("aaa2"); //合併List List<String> collect = list1.stream().filter(s -> list2.contains(s)).collect(Collectors.toList()); System.out.println("============多個List合併後的元數據==========="); System.out.println(collect); // 獲得元素出現頻率的 Map,鍵爲元素,值爲元素出現的次數 List<String> collect1 = collect.stream().collect(Collectors.toMap(a -> a, a -> 1, (a, b) -> a + b)) // Set<Entry>轉換爲Stream<Entry> .entrySet().stream() // 過濾出元素出現次數大於 1 的 entry .filter(entry -> entry.getValue() > 1) // 獲得 entry 的鍵(重複元素)對應的 Stream .map(entry -> entry.getKey()) // 轉化爲 List並去重 .distinct().collect(Collectors.toList()); System.out.println("========合併後得到處理得到重複的數據========"); System.out.println(collect1); }
輸出結果如下