Stream API

例子见Github-JavaSE-Day08

Stream

Stream是一组用来处理数组、集合的API
JAVA8 费大力气引入函数式编程,原因:

  1. 多核友好(并行计算),JAVA函数式编程使得并行程序非常简单,就是需要调用一下parallel()方法。
  2. 代码简洁。函数式编程写出的代码简洁且意图明确,使用Stream接口让你从此告别for循环。

特性:

  1. 不是数据结构,没有内部存储
    集合中进行了非常多操作,中间的迭代过程是不支持数据存储的。分为中间操作和执行操作,只有进行执行算子,整个流才会执行
  2. 不支持索引访问
  3. 延迟计算
  4. 支持并行
  5. 很容易生成数组或集合
  6. 支持过滤、查找、转换、汇总、聚合等操作

  • Stream分为:源source中间操作终止操作
  • 流的源可以是一个数组、一个集合、一个生成器方法、一个I/O通道等待
  • 一个流可以有0或多个中间操作,每个中间操作返回一个新的流,供下一个操作使用
  • 一个流只有一个终止操作。Stream只有遇到终止操作,它的源才会开始执行遍历操作
Stream的创建
  1. 通过数组生成
  2. 通过集合生成
  3. 通过Stream.generate()
  4. 通过Stream.iterate()
  5. 其他API创建
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    public class StreamDemo {
    // 通过数组生成
    static void gen1() {
    String[] strs = {"a","b","c","d"};
    // 数组转换为一个Stream
    Stream<String> strs1 = Stream.of(strs);
    /**
    * forEach参数是Consumer<? super T> action
    * Consumer<T>代表一个输入的函数式接口
    * System.out::println是一个实例方法引用
    */
    strs1.forEach(System.out::println);
    }

    // 通过集合生成
    static void gen2() {
    List<String> list = Arrays.asList("1","2","3","4");
    Stream<String> stream = list.stream();
    stream.forEach(System.out::println);
    }

    //通过generate()
    static void gen3() {
    /**
    * generate()返回无限顺序无序流,其中每个元素是由提供的Supplier,无限循环
    * Supplier,代表一个输出
    */

    Stream<Integer> generate = Stream.generate(() -> 0);
    generate.limit(3).forEach(System.out::println); // 限制3次
    }
    // 使用iterator
    static void gen4() {
    /**
    * iterate()参数是UnaryOperator<T> f,无限循环
    * UnaryOperator<T> f,一个输入一个输出,类型相同
    */
    Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);
    iterate.limit(3).forEach(System.out::println);
    }
    //其他方式
    static void gen5() {
    String str = "abcd";
    IntStream stream = str.chars();
    stream.forEach(System.out::println);
    }
    public static void main(String[] args) {
    gen1();
    gen2();
    gen3();
    gen4();
    gen5();
    }
    }
    结果:
    a
    b
    c
    d
    1
    2
    3
    4
    0
    0
    0
    1
    2
    3
    97
    98
    99
    100
Stream常用API

中间操作:如果返回值是Stream对象,意味着是中间操作
延迟操作可以省掉很多临时存储的空间

StreamDemo.java
public static void main(String[] args) {
    //------中间操作:如果返回值是Stream对象,意味着是中间操作
    // 取出偶数
    Arrays.asList(1,2,3,4,5).stream()
            .filter((x)->x % 2 == 0).forEach(System.out::println);
    // 求出结果集中的所有偶数的和
    long count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()
            .filter(x -> x % 2 == 0).mapToInt(x->x).sum();
    System.out.println(count);
    // 求集合中最大值
    List list = Arrays.asList(7,1,2,3,4,5,6);
    Optional max = list.stream().max((a, b) -> a - b);
    System.out.println(max.get());
    // 求集合中最小值
    System.out.println(list.stream().min((a,b)->a-b).get());

Optional<Integer> any = list.stream().filter(x -> x % 2 == 0).findAny();
System.out.println(any.get());

// 如果没有这个值会报错:no value present
Optional<Integer> first = list.stream().filter(x -> x % 2 == 0).findFirst();
System.out.println(first.get());

Stream<Integer> integerStream = list.stream().filter(i -> {
    System.out.println("运行代码"); // 不会被打印  延迟执行 一直等于stream一直不执行
    return i % 2 == 0;
});
System.out.println(integerStream);
System.out.println(integerStream.findAny().get());
System.out.println("---------------");
    //获取最大值和最小值,但是不使用min和max方法
    Optional<Integer> min = list.stream().sorted().findFirst();
    System.out.println(min.get());
    Optional<Integer> max2 = list.stream().sorted((a,b)->b-a).findFirst();
    System.out.println(max2.get());

    //按照自然序排序
    Arrays.asList("java","c#","python","scala","jee").stream().sorted().forEach(System.out::println);
    //按照长度排序
    System.out.println("+++++++++++");
    Arrays.asList("java","c#","python","scala","jee").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);
    System.out.println("=============");
    // 想将集合中的元素进行过滤同时返回一个集合对象
    List<Integer> collect = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
    collect.forEach(System.out::println);
    // 去重操作
    Arrays.asList(1,2,2,3,3,3,4,5,2).stream().distinct().forEach(System.out::print);
    System.out.println();
    Arrays.asList(1,2,2,3,3,3,4,5,2).stream().collect(Collectors.toSet()).forEach(System.out::print);
    System.out.println();
    // 打印20~30这样的集合数据
    Stream.iterate(1,x->x+1).limit(50).skip(20).limit(10).forEach(System.out::print);
    System.out.println();
    // 字符串值求和
    String str = "11,22,33,44,55";
    System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());
    System.out.println(Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum());
    System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());
    System.out.println(Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum());

    // 创建一组自定义对象
    String str2 = "java,scala,python";
    Stream.of(str2.split(",")).map(x->new Person(x)).forEach(System.out::print);
    System.out.println();
    Stream.of(str2.split(",")).map(Person::new).forEach(System.out::print);
    System.out.println();
    Stream.of(str2.split(",")).map(x->Person.build(x)).forEach(System.out::print);
    System.out.println();
    Stream.of(str2.split(",")).map(Person::build).forEach(System.out::print);
    // 将str中每个数值都打印出来同时算出最终的求和结果
    // peek(IntConsumer action)返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作
    System.out.println(Stream.of(str.split(",")).peek(System.out::println).mapToInt(Integer::valueOf).sum());

    // list:{7,1,2,3,4,5,6}
    // allMatch(IntPredicate predicate)返回此流的所有元素是否与提供的谓词匹配
    System.out.println(list.stream().allMatch(x -> x % 2 == 0));
    System.out.println(list.stream().anyMatch(x -> x % 2 == 0)); // 任何一个true

}

Person.java
2
public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public Person() {
    }
    public static Person build(String name) {
        Person p = new Person();
        p.setName(name);
        return p;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
结果
2
4
20
7
1
2
2
java.util.stream.ReferencePipeline$2@312b1dae
运行代码
运行代码
运行代码
2
---------------
1
7
c#
java
jee
python
scala
+++++++++++
c#
jee
java
scala
python
=============
2
4
6
12345
12345
21222324252627282930
165
165
165
165
Person{name='java'}Person{name='scala'}Person{name='python'}
Person{name='java'}Person{name='scala'}Person{name='python'}
Person{name='java'}Person{name='scala'}Person{name='python'}
Person{name='java'}Person{name='scala'}Person{name='python'}
22
33
44
55
165
false
true