Stream API

使用Stream API对集合数据进行操作,就类似于使用sql执行数据库查询。

Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是有关计算的。前者主要是面向内存,存储在内存中,后者主要是面向CPU的,通过CPU实现计算。

Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,Stream讲的是计算

  • Stream 自己不会存储元素
  • Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream
  • Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才执行

创建Stream

  • java8中的Collection接口被扩展,提供了两个获取流的方法:
    • default Stream stream() 返回一个数据流
    • default Stream parallelStream() 返回一个并行流
public void createStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    Stream<String> stream = list.stream();
    Stream<String> parallelStream = list.parallelStream();
}
  • java8 中的Arrays静态方法stream() 可以获取数组流
    • public static Stream stream(T[] array) 返回一个流
public void createStream() {
    Stream<String> arrStream = Arrays.stream(new String[]{"北京", "南京"});
}
  • 可以调用Stream类的静态方法of(),通过显示值创建一个流,它可以接受任意数量的参数
    public static Stream of(T... values)
@Test
public void createStream() {
    Stream<String> streamOf = Stream.of("北京", "南京");
}

Stream的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何的处理。而在终止操作时一次性全部处理,称为惰性求值。

1. 筛选与切片:

  • filter(Predicate p) 接收Lambda,从流中排除某些元素
  • distinct() 筛选,通过流所生成的元素的hasCode()和equals()去除重复元素
  • limit(long maxSize) 截断流,使其元素不超过给定数量
  • skip(long n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
@Test
public void operateStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    list.add("上海");
    list.add("西安");
    list.add("厦门");
    list.add("兰州");
    list.add("石河子");
    list.add("乌鲁木齐");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    Stream<String> stream = list.stream();
    stream.filter(s -> s.length() > 2).forEach(System.out::println);
    System.out.println("******************limit***********************");
    stream = list.stream();
    stream.limit(3).forEach(System.out::println);
    System.out.println("******************skip***********************");
    stream = list.stream();
    stream.skip(6).forEach(System.out::println);
    System.out.println("******************distinct***********************");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    stream = list.stream();
    stream.distinct().forEach(System.out::println);
}

2. 映射:

  • map(Function f) 接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
  • mapToDouble(ToDoubleFunction f) 接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream
  • mapToInt(ToIntFunction) 接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream
  • mapToLong(ToLongFunction f) 接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream
  • flatMap(Function f) 接受一个函数作为参数,该函数将流中的每个值都换成另一个流,然后把所有流连接成一个流
@Test
public void mapStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    list.add("上海");
    list.add("西安");
    list.add("厦门");
    list.add("兰州");
    list.add("石河子");
    list.add("乌鲁木齐");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    Stream<String> stream = list.stream();
    stream.map(s -> s + "2019").forEach(System.out::println);
    System.out.println("******************不使用flatMap***********************");
    stream = list.stream();
    Stream<Stream<Character>> streamStream = stream.map(StreamAPI::fromStringToStream);
    streamStream.forEach(s -> s.forEach(System.out::println));
    System.out.println("******************flatMap***********************");
    stream = list.stream();
    Stream<Character> characterStream = stream.flatMap(StreamAPI::fromStringToStream);
    characterStream.forEach(System.out::println);
}

public static Stream<Character> fromStringToStream(String str) {
    List<Character> characterList = new ArrayList<>();
    for(Character c : str.toCharArray()) {
        characterList.add(c);
    }
    return characterList.stream();
}

3. 排序:

  • sorted() 产生一个新流,其中按自然顺序排序
  • sorted(Comparator com) 产生一个新流,其中俺比较器顺序排序
@Test
public void sortStream() {
    List<String> list = new ArrayList<>();
    list.add("10北京");
    list.add("9南京");
    list.add("8上海");
    list.add("7西安");
    list.add("6厦门");
    list.add("5兰州");
    list.add("4石河子");
    list.add("3乌鲁木齐");
    list.add("2斯洛伐克");
    list.add("1阿尔吉尼亚");
    Stream<String> stream = list.stream();
    stream.sorted().forEach(System.out::println);
    System.out.println("******************sorted(Comparator)***********************");
    stream = list.stream();
    stream.sorted((o1, o2) -> Integer.compare(o1.length(), o2.length())).forEach(System.out::println);
}

Stream的终止操作

终止操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List, Integer, void
流进行了终止操作后,不能再次使用

1. 匹配与查找:

  • allMatch(Predicate p) 检查是否匹配所有元素
  • anyMatch(Predicate p) 检查是否至少匹配一个元素
  • noneMatch(Predicate p) 检查是否没有匹配所有元素
  • findFirst() 返回第一个元素
  • findAny() 返回当前流中的任何元素
  • count() 返回流中元素的总数
  • max(Comparator c) 返回流中最大值、
  • min(Comparator c) 返回流中最小值
  • forEach(Comparator c) 内部迭代(使用Collection金额口需要用户去做迭代,称为外部迭代。相反,Stream使用内部迭代,他帮你把迭代做了)
@Test
public void matchStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    list.add("上海");
    list.add("西安");
    list.add("厦门");
    list.add("兰州");
    list.add("石河子");
    list.add("乌鲁木齐");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    Stream<String> stream = list.stream();
    boolean allMatch = stream.allMatch(s -> s.length() > 3);
    System.out.println(allMatch);
    System.out.println("******************anyMatch***********************");
    stream = list.stream();
    boolean anyMatch = stream.anyMatch(s -> s.length() > 3);
    System.out.println(anyMatch);
    System.out.println("******************noneMatch***********************");
    stream = list.stream();
    boolean noneMatch = stream.noneMatch(s -> s.length() > 3);
    System.out.println(noneMatch);
    System.out.println("******************findFirst***********************");
    stream = list.stream();
    Optional<String> first = stream.findFirst();
    System.out.println(first.get());
    System.out.println("******************findAny***********************");
    stream = list.stream();
    Stream<String> parallelStream = list.parallelStream();
    Optional<String> any = parallelStream.findAny();
    System.out.println(any.get());
    System.out.println("******************count***********************");
    stream = list.stream();
    long count = stream.count();
    System.out.println(count);
    System.out.println("******************max***********************");
    stream = list.stream();
    Optional<String> max = stream.max((o1, o2) -> Integer.compare(o1.length(), o2.length()));
    System.out.println(max.get());
    System.out.println("******************min***********************");
    stream = list.stream();
    Optional<String> min = stream.min((o1, o2) -> Integer.compare(o1.length(), o2.length()));
    System.out.println(min.get());
}

2. 归约

  • reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回T
  • reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回Optional
@Test
public void reduceStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    list.add("上海");
    list.add("西安");
    list.add("厦门");
    list.add("兰州");
    list.add("石河子");
    list.add("乌鲁木齐");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    Stream<String> stream = list.stream();
    Optional<String> reduce = stream.reduce((s1, s2) -> s1 + s2);
    System.out.println(reduce.get());
    System.out.println("*****************************************");
    stream = list.stream();
    String hello = stream.reduce("hello", (s1, s2) -> s1 + s2);
    System.out.println(hello);
}

3. 收集:

  • collect(Collector c) 将流转换成其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法

Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。
另外,Collectors实用类提供了很多静态方法,可以方便的创建常见的收集器实例,具体方法与实例:

  • toList() 把流中元素收集到List
  • toSet() 把流中元素收集到Set
  • toCollection() 把流中元素收集到查ungjiande集合
  • counting() 计算流中元素个数
  • summingInt() 对流中元素的整数属性求和
  • averagingInt 计算流中元素Integer属性的平均值
  • summarizingInt() 收集流中Integer属性的统计值。如:平均值
@Test
public void collectStream() {
    List<String> list = new ArrayList<>();
    list.add("北京");
    list.add("南京");
    list.add("上海");
    list.add("西安");
    list.add("厦门");
    list.add("兰州");
    list.add("石河子");
    list.add("乌鲁木齐");
    list.add("斯洛伐克");
    list.add("阿尔吉尼亚");
    list.add("阿尔吉尼亚");
    Stream<String> stream = list.stream();
    List<String> collectList = stream.filter(s -> s.length() > 3).collect(Collectors.toList());
    System.out.println("********************toSet*********************");
    stream = list.stream();
    Set<String> collectSet = stream.filter(s -> s.length() > 3).collect(Collectors.toSet());
    System.out.println(collectSet);
    System.out.println("********************toCollection*********************");
    stream = list.stream();
    ArrayList<String> collectCollection = stream.filter(s -> s.length() > 3).collect(Collectors.toCollection(ArrayList::new));
    System.out.println(collectCollection);
    System.out.println("********************counting*********************");
    stream = list.stream();
    Long counting = stream.filter(s -> s.length() > 3).collect(Collectors.counting());
    System.out.println(counting);
}

你可能感兴趣的:(Java学习,Stream,API)