Stream的实例化
关于Stream的实例化,java中给出了四种实例化的方式
Stream实例化方式一: ---- > 通过集合
获得一个顺序流对象
调用方法:default Stream< E> stream();
- 使用集合调用这个stream()方法,会返回一个顺序流
- 这里返回的是一个顺序流,因为这个时候这个流加载集合中的元素的时候是一个元素一个元素进行加载的,这个时候这个流中就是按照加载的顺序
- 这个方法定义在了接口中,所以这个方法声明为default(默认的)
- 这里我们说这个方法定义在了接口中不仅仅是说这个方法声明在接口中,而是说这个方法的具体实现也是在接口中实现的,这个时候接口中的实现方法就是定义为default的方法
eg:
package stream流;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo1 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("123");
arrayList.add("124");
arrayList.add("125");
arrayList.add("126");
/*
这个时候我们就是通过这个ArrayList<String>类型的一个集合对象调用了Collection接口中的stream()方法
得到了这个集合的顺序流对象
*/
Stream<String> stream = arrayList.stream();
//这个时候我们直接调用了终止操作遍历了流中的内容
stream.forEach(System.out :: println);
}
}
获得一个并行流对象
调用方法: default Stream< E> parallelStream();
- 使用集合调用这个parallelStream()方法我们会得到一个并行流对象
- 这里返回的是一个并行流,因为这个时候这个流加载这个集合中的元素的时候是一次几个一次几个这样加载的 — > 就类似于我们的多线程一样,这个时候一次加载多个,这个时候就不能保证先后顺序,所以这个时候我们获得的并行流对象就不是按照我们的原本的集合的顺序的
- 这个方法也是定义在了接口中,这个时候我们要在接口中就具体实现这个方法,这个时候我们就只能将这个方法声明为default(默认的)
- 接口中到方法声明为default之后这个方法就不再是抽象方法,这个时候这个方法就可以有方法体
Stream实例化方式二: — > 通过数组
-
我们使用数组产生一个Stream流对象的时候我们就是调用Arrays类中的stream()静态方法,这个时候我们根据这个我们这个方法中传入的数组的元素类型不同我们就会调用不同的重载方法
-
关于我们调用的重载方法我们大致可以分为两类
-
static < T> Stream< T> stream(T [] arr);
- 这个时候我们如果传入的这个数组是一个存储引用类型数据的数组,这个时候我们就是调用的这个方法
- 这个方法是一个泛型方法
- 这个方法返回值以泛型的形式体现
-
static < T> XxxStream stream(xxx [] arr);
-
这个方法中的xxx是一个基本数据类型,也就是当我们的这个方法中传入的数组是一个存储基本数据类型的数组的时候,这时候我们就调用这个方法
-
这个方法也是一个泛型方法
-
这个方法的返回值以XxxStream的形式体现
-
这里我们举几个常见的第二种情况的实际方法
static < T> IntStream stream(int [] arr); ---- 数组为int类型
static < T> LongStream stream(Long [] arr); ---- 数组为long类型
-
-
-
eg:
这里我们举两个例子:
- 第一个就是当我们Arrays.stream()方法中的参数数组中存放的元素为引用类型时:
- 首先我们要创建一个自定义类,我们就是要创建一个这个自定义类类型的数组
package stream流;
public class Employee {
private int age;
private String name;
public Employee(){
}
public Employee(int age, String name){
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Employee{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
- 然后我们在创建一个Employee类型的数组,然后再通过使用Arrays类中的stream()方法,将我们创建的Employee类型的数组作为参数传入这个方法中,然后我们就可以获得对应的流对象
package stream流;
import java.util.Arrays;
import java.util.stream.Stream;
public class Demo2 {
public static void main(String[] args) {
Employee e1 = new Employee(20,"马云");
Employee e2 = new Employee(30,"马化腾");
Employee [] arr = new Employee[]{e1,e2};
/*
这里我们就是通过调用Arrays类中的stream()方法得到了对应的流对象
注意: 这个方法是一个泛型方法,这个泛型方法的泛型是通过传入这个方法的数组的类型确定的
所以这个方法的返回值,也就是返回的Stream对象的泛型就是传入这个方法中作为参数的数组的类型
*/
Stream<Employee> stream = Arrays.stream(arr);
/*
这个时候我们没有使用中间操作,直接使用终止操作将这个流中的数据输出了出来
*/
stream.forEach(System.out :: println);
}
}
- 这个时候我们调用的是static < T> Stream< T> stream();
- 这个方法的返回值为Stream< T>,这个时候的返回值是以泛型的形式体现出来的
- 这个时候之所以调用的是这个方法,是因为这个时候我们的这个stream()方法中传入的是一个引用类型作为类型的数组
第二个就是当我们的Arrays.stream()方法中传入的数组类型为基本数据类型时(这里我们使用 int 类型的数组举例)
- 这个时候我们就直接创建一个int [] 然后给这个数组中添加元素,然后调用Arrays类中的stream()方法,然后将我们创建的int类型的数组作为参数传递到这个方法中作为这个方法的参数,然后这个方法就会给我们返回一个Stream流对象(更加确切的说是一个IntStream对象)
package stream流;
import java.util.Arrays;
import java.util.stream.IntStream;
public class Demo3 {
public static void main(String[] args) {
int [] arr = new int[]{1,2,3,4,5};
/*
这个时候我们就是通过调用Arrays类中的stream()方法,然后我们将我们创建的int类型的数组作为参数传递到这个方法中
作为这个方法的参数,然后我们就可以得到一个IntStream类型的对象
*/
IntStream intStream = Arrays.stream(arr);
/*
这时候我们直接通过我们得到的Stream流对象调用了一个终止操作进行了这个流对象的遍历,这个时候我们没有执行中间操作
*/
intStream.forEach(System.out :: println);
}
}
- 注意:这个时候我们调用的是 static < T> IntStream stream(int [] arr);
- 这个时候的返回值为IntStream类型,因为这个时候我们在这个方法中传入的数组类型是基本数据类型
Stream实例化方式三: — > 通过使用Stream类中的of()静态方法
调用方法:
public static < T> Stream< T> of(T …value);
- 这个方法的参数是一个可变形参(就是可变长度的参数)
- 可变形参的本质其实就是一个数组
- 这个方法是一个泛型方法
- 这个方法是一个静态方法
eg: 这里我们举一个例子:
package stream流;
import java.util.stream.Stream;
public class Demo4 {
public static void main(String[] args) {
/*
这个时候我们通过调用Stream类中的静态方法of(),然后给这个方法中传入多个数据(这个of()方法的参数是一个可变形参),
这个时候就会返回一个带泛型的Stream对象
*/
Stream<Integer> stream = Stream.of(1,2,3,4,5);
/*
这个时候我们使用我们获得的Stream对象直接进行了终止操作,进行了打印,而没有进行中间操作
这里我们说Stream流对象的中间操作是一个中间操作链
*/
stream.forEach(System.out :: println);
}
}
Stream实例化方式四: ----> 创建无限流
这里提供的创建无限流的方式有两种:
第一种: — > 迭代
调用方法 :
public static < T> Stream< T> iterate(final T seed , final UnavyOperator< T> f);
- 这个方法是一个静态方法
- 这个方法是一个泛型方法
- 这个方法的第一个参数是一个种子 — > 就是从这个种子开始,这个方法的第二个参数是一个一元函数函数式接口
- UnavyOperator接口的输入的参数和返回值的类型是同一种类型,这个接口是Function接口(函数接口)的一个子接口
这里我们举一个例子:
eg: 这个时候我们创建一个无限流 — 使用这个无限流遍历前十个偶数
package stream流;
import java.util.stream.Stream;
public class Demo5 {
public static void main(String[] args) {
/*
这个时候我们使用iterate()方法得到一个无限流对象,然后我们再通过使用一个中间操作limit()方法限制次数
然后我们再使用终止操作将这个无限流对象遍历这个无限流对象
*/
Stream.iterate(0,t -> t + 2).limit(10).forEach(System.out :: println);
}
}
第二种: ----> 生成
调用方法:
public static < T> stream< T> generate(Supplier< T> s)
- 这个方法是一个静态方法
- 这个方法是一个泛型方法
- 这个方法的参数是一个Supplier接口对象(供给型函数式接口对象)
- Supplier接口无参,但是有一个返回值
这里我们举一个例子:
eg: 这个时候我们创建一个无限流 — 使用这个无限流产生十个 0.0到1.0之间的数(可以为0.0,但是不可以为1.0)
package stream流;
import java.util.stream.Stream;
public class Demo6 {
public static void main(String[] args) {
/*
这个时候我们创建了一个无限流对象,然后通过这个无限流对象调用中间操作限制执行次数,然后又调用了终止操作对这个流进行打印
*/
Stream.generate(Math :: random).limit(10).forEach(System.out :: println);
}
}