Java 8 引入了流式操做,位於java.util.stream包中。Stream API藉助Lambda表達式,提升編程效率和程序可讀性,如下記錄一些經常使用的流式操做方法。java
爲了便於下面演示,定義一個學生類。編程
public class Student { private Integer Id; private String name; private Integer age; private String gender; private String className; public Student() { } public Student(Integer id, String name,Integer age,String gender, String className) { Id = id; this.name = name; this.age = age; this.gender = gender; this.className = className; } public Integer getId() { return Id; } public void setId(Integer id) { Id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Student{" + "Id=" + Id + ", name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + ", className='" + className + '\'' + '}'; }}
在測試類中,初始化學生對象數據。數組
public class Test { public static List<Student> students = new ArrayList<>(); static { students.add(new Student(1, "張三",15,"男","高一一班")); students.add(new Student(2, "李四",14,"男", "高一二班")); students.add(new Student(3, "王五", 14,"女","高一一班")); students.add(new Student(4, "趙六",16,"女", "高一二班")); }}
一、將數組轉爲列表。ide
String sArray[] = new String[]{"A", "B", "C"};//寫法一// 使用該方法轉換出的List,實際爲Arrays的一個嵌套類ArrayList,是Arrays類利用asList()方法產生的一個長度不可變的容器// 若是使用add方法,會報錯List<String> list = Arrays.asList(sArray);// list.add("w"); //報錯//寫法二List<String> list2 = new ArrayList<String>(Arrays.asList(sArray));//寫法三int iArray[] = new int[]{1, 2, 3};List<Integer> list3 = Arrays.Stream(iArray).boxed().collect(Collectors.toList());
二、列表轉數組(注:這個不屬於stream操做)。函數
Student[] students = Test.students.toArray(new Student[Test.students.size()]);
三、filter 過濾。在Student集合中,篩選出高一一班的同窗,並將其封裝成爲一個新的List。測試
//寫法一,foreach寫法List<String> studentNames = new ArrayList<>();students.forEach(student -> studentNames.add(student.getName()));//寫法二,stream寫法List<String> names = students.stream().map(Student::getName).collect(Collectors.toList());
四、distinct 去重。獲取全部學生的班級。this
List<String> list = students.stream().map(Student::getClassName).distinct().collect(Collectors.toList());
五、limit 返回前n個元素,當集合元素少於n個,則返回全部元素。獲取前2個學生。對象
List<Student> collect = students.stream().limit(2).collect(Collectors.toList());
六、sorted 排序。根據年齡,從大到小排序。blog
List<Student> collect = students.stream().sorted((s1, s2) -> s2.getAge() - s1.getAge()).collect(Collectors.toList());
七、skip 跳過前n個元素。忽略前三個學生。排序
List<Student> collect = students.stream().skip(3).collect(Collectors.toList());
八、map 映射。取出學生名稱。
List<String> names = students.stream().map(Student::getName).collect(Collectors.toList());
九、flatMap,將一個流中的每一個值都轉成一個個流,再將這些流扁平化成爲一個流。
String[] strings = {"good", "data"};//若是拆分後直接輸出,獲取到的會是一個數組列表,List<String[]> collect = Arrays.asList(strings).stream().map(s -> s.split("")).collect(Collectors.toList());System.out.println(collect);//列表的元素,爲數組 //使用flatMap,使多個流,變成一個流List<String> collect2 = Arrays.asList(strings).stream().map(s -> s.split("")).flatMap(strings1 -> Arrays.Stream(strings1)).collect(Collectors.toList());System.out.println(collect2);//[g, o, o, d, d, a, t, a]
十、allMatch,檢測是否所有都知足指定的參數行爲,若是所有知足則返回true。例如判斷是否全部的學生都屬於高一一班。
boolean isMatch = students.stream().allMatch(student -> student.getClassName().equals("高一一班"));
十一、anyMatch,檢測是否存在至少一個知足指定的參數行爲,若是存在則返回true。例如判斷學生中,是否有屬於高一一班的學生。
boolean hasMatch = students.stream().anyMatch(student -> student.getClassName().equals("高一一班"));
十二、noneMatch,檢測是否所有都不知足指定的參數行爲,若是所有都不知足則返回true,例如判斷是否全部的學生都不屬於高二一班。
boolean isMatch = students.stream().noneMatch(student -> student.getClassName().equals("高二一班"));
1三、findFirst,返回符合條件的第一個數據。
Optional<Student> firstOption = students.stream().filter(student -> student.getClassName().equals("高一一班")).findFirst();//使用get,若是沒有查找到,會拋出異常 NoSuchElementExceptionStudent student = firstOption.get();//使用orElse或者orElseGet,若是沒有查找到,則使用默認值返回,例如這裏默認返回一個空的學生對象Student student1 = firstOption.orElse(new Student());Student student2 = firstOption.orElseGet(() -> new Student());
1四、findAny,返回符合條件的任意一個數據。
Optional<Student> firstOption = students.stream().filter(student -> student.getClassName().equals("高一一班")).findAny();//使用get,若是沒有查找到,會拋出異常 NoSuchElementException,能夠使用orElse或者orElseGet,當沒有查找到,使用默認值返回Student student = firstOption.get();
1五、count,計算數量,例如計算高一一班人數。
long size = students.stream().filter(student -> student.getClassName().equals("高一一班")).count();
1六、maxBy、minBy,獲取最大最小值。
//兩種方式獲取年齡最大的學生Student student1 = students.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get();Student student2 = students.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getId))).get();//兩種方式獲取年齡最小的學生Student student3 = students.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get();Student student4 = students.stream().collect(Collectors.minBy(Comparator.comparing(Student::getId))).get();
1七、sum,計算某個字段值總和。計算年齡總和。
//方式一Integer sum = students.stream().collect(Collectors.summingInt(Student::getAge));//方式二int sum1 = students.stream().mapToInt(Student::getAge).sum();
1八、average,計算某個字段的平均值。計算年齡平均值。
//方式一Double average = students.stream().collect(Collectors.averagingInt(Student::getAge));//方式二double asDouble = students.stream().mapToInt(Student::getAge).average().getAsDouble();
1九、summary。一次性得出元素個數,總和,最大值,最小值和平均值。
IntSummaryStatistics collect = students.stream().collect(Collectors.summarizingInt(Student::getAge));System.out.println(collect);//IntSummaryStatistics{count=4, sum=59, min=14, average=14.750000, max=16}
20、joining,字符串拼接。拼接學生名字。
String names = students.stream().map(Student::getName).collect(Collectors.joining(","));System.out.println(names);//張三,李四,王五,趙六
2一、groupingBy,分組。例如根據班級分組。
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getClassName));
2二、partitionBy,分區。能夠認爲是分組的一種特殊狀況,根據返回值爲true/false,將集合按條件一分爲二,例如根據性別,一分爲二。
Map<Boolean, List<Student>> map = students.stream().collect(Collectors.partitioningBy(student -> student.getGender().equals("男")));
2三、toMap。將列表轉爲map。
//使用toMap,若是key重複,會報錯Map<Integer, String> collect = students.stream().collect(Collectors.toMap(Student::getId, Student::getName));//能夠指定key衝突解決方法。例如若是key重複,使用第二個key覆蓋第一個key (key1, key2) -> key2Map<String, Student> collect1 = students.stream().collect(Collectors.toMap(Student::getClassName, Student -> Student, (key1, key2) -> key2));
2四、reduce,歸約操做。reduce能夠實現從一組值中,生成一個值。
reduce接收兩個參數,第一個參數爲最終生成值的初始值,第二個參數爲一個函數,用於計算當前生成值與遍歷到的元素的操做邏輯。
// 使用reduce求和Integer reduce = Stream.of(1, 2, 3).reduce(0, (curSum, newData) -> curSum += newData);System.out.println(reduce);//6// 使用reduce,獲取年齡最大的學生。初始化爲第一個學生。Student finalStudent = students.stream().reduce(students.get(0), (curStudent, newStudent) -> { if (curStudent.getAge() < newStudent.getAge()) { return newStudent; } return curStudent;});System.out.println(finalStudent);//Student{Id=4, name='趙六', age=16, gender='女',