Stream流,是JDK1.8中对集合对象功能的增强,可以通过将集合转换为流模型,通过声明的方式对集合中个每个元素进行一系列并行或者串行的流水线操作。
Stream只要给出对其包含的元素执行什么操作,Stream就会隐式地在内部进行遍历,并给出响应的数据转换。单向不可往复、数据只能遍历一次,遍历过后就使用完毕。
Stream可以并行化操作,Stream的并行操作是依赖Java7中引入的Fork/Join框架拆分任务和加速处理过程,并且允许数据源是无限的。
使用Stream可以简化代码,使代码简洁易读;如果通过使用parallelStream可以启动并发模式,使程序执行速度更快
Stream使用实例
从数据源中获取一组用户信息,查找年满18周岁以上的所有用户,然后针对用户信息按照工资值进行倒序排序,获取所有用户的id编号,随机生成用户信息,并存储在List中
public class User {
private Long id;
private String name;
private Double Starly;
private int age;
public User() {
}
public User(Long id, String name, Double starly) {
this.id = id;
this.name = name;
this.Starly = starly;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getStarly() {
return Starly;
}
public void setStarly(Double starly) {
Starly = starly;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", Starly=" + Starly + ", age=" + age + "]"+"\n";
}
}
public class Test01 {
public static void main(String[] args) {
List userList = new ArrayList<>();
Random r = new Random();
for (int i = 1; i < 11; i++) {
User tmp = new User();
tmp.setId(i+0L);
tmp.setName("name-"+i);
tmp.setStarly(r.nextDouble()*9000+10000);
tmp.setAge(r.nextInt(10)+18);
userList.add(tmp);
}
System.out.println(userList);
System.out.println("======================");
List uList = new ArrayList<>();
for (User tmp:userList) {
if (tmp.getAge()>18) {
uList.add(tmp);
}
}
Collections.sort(uList,new Comparator() {
@Override
public int compare(User o1, User o2) {
return o2.getStarly().compareTo(o1.getStarly());
}
});
List idList = new ArrayList<>();
for (User tmp:uList) {
idList.add(tmp.getId());
}
System.out.println(idList);
//使用Stream
userList.stream().filter(t->t.getAge()>18).sorted((u1,u2)->u2.getStarly().compareTo(u1.getStarly()))
.map(User::getId).forEach(System.out::println);
}
}
使用Stream通常包括3个基本步骤:获取一个数据源source---转换为流---执行操作---获取所想要的结果。每次转换原有的Stream对象,执行结果还是Stream,可以使用串式写法定义多个操作。
数据源就是原始的数据集合
将List
针对Stream进行一系列操作,每次操作结束返回还是Stream
可以将Stream转换回集合类型,也可以直接对其中的元素进行处理
1、创建Stream
2、转换Stream,每次执行转换Stream对象类型不改变,返回一个新的Stream对象
3、对Stream进行聚合操作,获取想要的结果
流stream可以是顺序的,也可以是并行的。顺序流的操作是在单线程上执行,而并行流是在多线程上并发执行的。
1、可以使用Arrays.stream将一组数据转换为Stream
2、使用Collection.parallelStream使用并行流,处理任务并行执行。前提是硬件支持
也可以使用Collection.stream使用串行流
3、对于基本类型目前有3中对应的包装类型Stream:IntStream、LongStream和DoubleStream。如果不使用对应的Stream类型,也可以使Stream
4、从输入流中获取数据的方法
可以使用BufferedReader生成stream,把流中的内容一行一行的读取出来
5、创建无限流的方法
generate方法可以接收一个参数函数用于创建无限stream
//1.使用Arrays.stream将一组数据转换为Stream
Integer[] arr=new Integer[]{3,4,6,8,9,23,232,33,96};
long count=Arrays.stream(arr).filter(i->i>20).count();//统计大于20的数据个数
//2.使用Collection.parallelStream使用并行流
List list = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream stream = list.parallelStream();
stream.forEach(System.out::println);
//3.了常用的基本数据类型的对应Stream
//参数类型为int...不确定个数的参数,可以根据参数生成一个stream
IntStream.of(3, 5, 18, 1, 4).forEach(System.out::println);
System.out.println("-----------------------------");
//根据指定的返回生成一组连续值,1-10含左不含右
IntStream.range(1, 10).forEach(System.out::println);
System.out.println("-----------------------------");
//根据指定的返回生成一组连续值,10-20含左含右
IntStream.rangeClosed(10, 20).forEach(System.out::println);
//5.使用BufferedReader生成stream
BufferedReader br = new BufferedReader(new FileReader("input/data.txt"));
Stream stream4=br.lines();
stream.forEach(System.out::println);
//4.generate方法可以接收一个参数函数用于创建无限stream
Stream stream5 = Stream.generate(() -> "test");
//stream.forEach(System.out::println);
// 获取前10个String转换为String[]
String[] brr = stream.limit(10).toArray(String[]::new);
System.out.println(Arrays.toString(brr));
Stream提供了forEach可以迭代流中的每个数据,forEach方法可以接收一个lambda表达式,并且在每个元素上执行该表达式,但是注意不能修改本地变量值,也不能break/return之类的关键字提前结束循环
随机数的输出前10个值
Random r = new Random();
r.ints().limit(10).forEach(System.out::println);
System.out.println("----------------------");
r.ints().limit(10).forEach((tt) -> {
if(tt>10)
System.out.println(tt);
});