简介
-
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
-
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
-
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
-
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
-
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
语法
Stream流的三个操作步骤
- 创建Stream
一个数据源(如:集合,数组),获取一个流 - 中间操作
一个中间链,对数据源数据进行处理 - 终止操作
一个终止操作,执行中间链,并产生结果
创建stream
@Test
public void test(){
// 1. 通过collection的stream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
// 2. 通过Arrays的stream()
User[] users = new User[10];
Stream<User> stream2 = Arrays.stream(users);
// 3. 通过Stream的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
// 4. 创建无限流
// 迭代
Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
stream4.limit(10).forEach(System.out::println);
// 生成
Stream.generate(() -> Math.random())
.limit(10).forEach(System.out::println);
}
中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理!而在终止操作时一次性全部处理,称为:“惰性求值”。
- 筛选与切片
- filter—接收Lambda,从流中排除某些元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); // 中间操作,不会执行任何操作 Stream<User> userStream = users.stream() .filter(user -> { System.out.println("Stream 操作"); return user.getAge() > 19; }); // 终止操作:一次性执行全部内容,即惰性求值 userStream.forEach(System.out::println); }
- limit—截断流,使其元素不超过给定数量
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); // 中间操作,不会执行任何操作 users.stream() .filter(user -> { System.out.println("短路"); return user.getAge() > 19; }) .limit(2) .forEach(System.out::println); }
- skip(n)—跳过元素,返回一个扔掉了n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); // 中间操作,不会执行任何操作 users.stream() .filter(user -> user.getAge() > 18) .skip(1) .forEach(System.out::println); }
- distinct—筛选,通过流所生成元素的hashcode()和equals()去除重复元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); // 中间操作,不会执行任何操作 users.stream() .filter(user -> user.getAge() > 18) .skip(1) .distinct() .forEach(System.out::println); }
- 映射
- map—接收Lambda,将元素转换为其他形式或提取信息,接收一个函数做参数该函数会被应用到每个参数上,并将其映射成一个新的元素
@Test public void test1(){ List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); users.stream() .map(User::getName) .forEach(System.out::println); } @Test public void test2(){ List<String> list = Arrays.asList("aaa", "bbb", "ccc"); Stream<Stream<Character>> streamStream = list.stream() .map(TestStreamAPI3::filterCharacter); streamStream.forEach(action -> { action.forEach(System.out::println); }); } // 将字符串转化为字符流 private static Stream<Character> filterCharacter(String str){ List<Character> list = new ArrayList<>(10); for (char c : str.toCharArray()) { list.add(c); } return list.stream(); }
- flatMap—接收一个函数作为参数,将流中的每个值都换成另一个流,然后把这些流连接成一个流
// 与上方map形成对比 @Test public void test3(){ List<String> list = Arrays.asList("aaa", "bbb", "ccc"); Stream<Character> stream = list.stream() .flatMap(TestStreamAPI3::filterCharacter); stream.forEach(System.out::println); } // 将字符串转化为字符流 private static Stream<Character> filterCharacter(String str){ List<Character> list = new ArrayList<>(10); for (char c : str.toCharArray()) { list.add(c); } return list.stream(); }
- 排序
- sorted—自然排序
@Test public void test(){ // 自然排序 List<String> list = Arrays.asList("bbb", "aaa", "ccc"); list.stream().sorted().forEach(System.out::println); }
- sorted(Comparator com)—定制排序
@Test public void test(){ // 定制排序 List<User> users = Arrays.asList(new User("xyn",20), new User("zyn",20)); // 进行排序的对象必须实现Comparable接口(否则会报错) // users.stream().sorted().forEach(System.out::println); users.stream().sorted((u1,u2) -> { if(u1.getAge() == u2.getAge()){ return u1.getName().compareTo(u2.getName()); }else{ return u1.getAge().compareTo(u2.getAge()); } }).forEach(System.out::println); }
终止操作
- 查找与匹配
- allMatch—检查是否匹配所有元素
public class User { private String name; private Integer age; private Status status; public User(String name, Integer age) { this.name = name; this.age = age; } public User(String name, Integer age, Status status) { this.name = name; this.age = age; this.status = status; } public User() { } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", status=" + status + '}'; } public enum Status{ FREE, BUSY, VOCATION; } } @Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); boolean b = users.stream() .allMatch(e -> e.getStatus().equals(User.Status.BUSY)); System.out.println(b); }
- anyMatch—检查是否至少匹配一个元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); boolean b = users.stream() .anyMatch(e -> e.getStatus().equals(User.Status.BUSY)); System.out.println(b); }
- noneMatch—检查是否没有匹配所有元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); boolean b = users.stream() .noneMatch(e -> e.getStatus().equals(User.Status.BUSY)); System.out.println(b); }
- findFirst—返回第一个元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); Optional<User> optionalUser = users.stream() .findFirst(); System.out.println(optionalUser.get()); }
- findAny—返回当前流中的任意元素
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); Optional<User> optionalUser = users.stream() .filter(e -> e.getStatus().equals(User.Status.FREE)) .findAny(); System.out.println(optionalUser.get()); }
- count—返回流中元素的总个数
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); long count = users.stream() .count(); System.out.println(count); }
- max—返回流中的最大值
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); Optional<User> max = users.stream() .max((u1, u2) -> Integer.compare(u1.getAge(), u2.getAge())); System.out.println(max.get()); }
- min—返回流中的最小值
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); Optional<Integer> min = users.stream() .map(User::getAge) .min(Integer::compareTo); System.out.println(min.get()); }
- 归约与收集(重要)
- reduce(T identity, BinaryOperator) / reduce(BinaryOperator)—可以将六中的元素反复结合起来,得到一个值
@Test public void test(){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE)); Integer sum = list.stream() .reduce(0, (x, y) -> x + y); System.out.println(sum); // 求年龄的和 Optional<Integer> optional = users.stream() .map(User::getAge) .reduce(Integer::sum); System.out.println(optional.get()); }
- collect—将流转化为其他形式。接收一个Collector接口的实现,用于给Stream中的元素做汇总的方法
@Test public void test(){ List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY), new User("zyn",20, User.Status.FREE), new User("ayn",40, User.Status.FREE)); // 放入集合 List<String> list = users.stream() .map(User::getName) .collect(Collectors.toList()); list.forEach(System.out::println); // 总和(年龄) Integer count = users.stream() .collect(Collectors.summingInt(User::getAge)); System.out.println(count); // 平均值(年龄) Double avg = users.stream() .collect(Collectors.averagingInt(User::getAge)); System.out.println(avg); // 最大值(年龄) Optional<Integer> max = users.stream() .map(User::getAge) .collect(Collectors.maxBy((u1, u2) -> Integer.compare(u1, u2))); System.out.println(max.get()); // 最小值(年龄) Optional<Integer> min = users.stream() .map(User::getAge) .collect(Collectors.minBy((u1, u2) -> Integer.compare(u1, u2))); System.out.println(min.get()); // 分组(按状态) Map<User.Status, List<User>> collect = users.stream() .collect(Collectors.groupingBy(User::getStatus)); System.out.println(collect); // 多级分组(先状态,后年龄) Map<User.Status, Map<String, List<User>>> collect1 = users.stream() .collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy(e -> { if (((User) e).getAge() <= 35) { return "青年"; } else { return "中年"; } }))); System.out.println(collect1); // 分区(按年龄分,大于20在一个区,其余在一个区) Map<Boolean, List<User>> collect2 = users.stream() .collect(Collectors.partitioningBy(e -> e.getAge() > 20)); System.out.println(collect2); // 功能统计 DoubleSummaryStatistics collect3 = users.stream() .collect(Collectors.summarizingDouble(User::getAge)); System.out.println(collect3.getMax()); System.out.println(collect3.getAverage()); System.out.println(collect3.getCount()); System.out.println(collect3.getSum()); // 连接(姓名) String collect4 = users.stream() .map(User::getName) .collect(Collectors.joining(",")); System.out.println(collect4); }
上一篇:Java8新特性之Lambda表达式(一)
下一篇:Java8新特性之Optional类(三)