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='女',