jdk8中新加入流Stream接口,主要为处理集合提供了便利,jdk8以后,在集合接口中新增加了默认的sream方法,用来生成流 对象结合Collection的源码增加的stream方法如下:
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
Stream可以看做是将流中的元素当作流水线上的产品来处理,比如一条传送履带,上面一个个元素传过来,进行处理
目录
Stream类
常用的四种创建流的方式:
匹配方法:
创建流的方法
工具方法
map和reduce
收集方法
IntStream接口
Optional类
OptionalInt类
OptionalDouble类
OptionalLong类
使用示例
1使用静态的of方法创建流
static
如Stream
Stream in=Stream.of(1,2,3,4,5)
2使用数组来创建
Arrays工具类有多个创建流的流的方法:
比如:int [] intArr={1,2,3,4}
IntStream is=Arrays.stream(intArr)
3静态方法iterate()创建无线流
static
例如:Stream s=Stream.iterate(1,i->i+1),返回一个i+1的流,1,2,3,.....
4通过集合的stream方法创建
因为Stream的增加主要是简化了集合的操作,所以集合的实现类肯定有Stream方法了
用法如下
List
如果集合中全是某一个类型的元素,创建集合的时候最好传入泛型,不然换成流后在流的方法中不能调用该类型的方法,因为流也不知道这种元素的类型是什么
下面介绍Stream类的常用方法:
boolean allMatch(Predicate predicate) 返回是否所有元素都匹配过滤条件predicate,全部符合,返回true,否则false
boolean anyMatch(Predicate predicate) 只要有一个元素复合传入的匹配条件,返回true,全不复合,返回false
boolean noneMatch(Predicate predicate) 判断是否所有元素都不匹配指定规则,都不匹配返回true
static
static
static
static
static
static
static
Optional
Optional
Stream
Stream
Stream
Stream
Stream
long count() 返回流中所有元素的个数 返回值为long类型
Stream
IntStream mapToInt(ToIntFunction mapper)将Stream中的元素通过指定方法后转换为IntStream流,
DoubleStream mapToDouble(ToDoubleFunction mapper)将Stream中的元素通过指定方法后转换为DoubleStream流
LongStream flatMapToLong(Function mapper)将Stream中的元素通过指定方法后转换为LongStream流
Optional
void forEach(Consumer action) 循环遍历
Object[] toArray() 生成一个包含流中所有元素的数组
上面提到collect方法需要的参数是Collector接口类型的,Collector是一个收集器,专门为collect方法设计,如果在API中没找到的方法,基本在collect方法都可以实现,Collectors是一个工具类,提供了很多静态方法,可以将Stream转换为集合或Map(容器中的Map)
比如collect(Collectors.toList)将Stream转换为List
在java.util.stream包下,IntStream主要来处理数值型数据,相比Stream增加了几个方法,简单介绍下
int sum()求流中所有元素的和
OptionalInt min()找出流中最小的元素的值
OptionalInt max()找出流中最大的元素的值
OptionalDouble average()求流中所有元素的平均值
static IntStream range(int startInclusive, int endExclusive)生成一个数值流,在两个参数之间,包括第一个参数,不包括第二个参数
static IntStream rangeClosed(int startInclusive, int endInclusive)生成一个数值流,在两个参数之间,包括第一个参数,也包括第二个参数
相似的接口还有DoubleStream,LongStream
java.util.Optional Optinal类主要是防止出现空指针异常,省去了非空指针判断
常用方法:使用Optional时,跟Stream一样,如果没指定泛型,则在Optional的方法中不能直接使用该类的方法,因为它不能自动识别值属于哪个类
static
static
static
T orElse(T other)如果Optional对象的值存在,返回值,如果不存在,为空,则返回指定值
T get() 得到optional对象的值
void ifPresent(Consumer consumer) 如果Optional对象的值存在,根据消费者接口的方法处理,如不存在,什么也不做
Optional
boolean isPresent() 判断值是否存在
Optional map(Function mapper) 存过值存在,对齐处理,如果处理后的结果存在返回Optional实例
OptionalInt类
int getAsInt()得到optinalInt类型的值
double getAsDouble()得到optinalDouble类型的值
long getAsLong()得到optinalLong类型的值
为了方便,先提供一个自定义的创建集合的类:
import java.util.ArrayList;
import java.util.List;
public class Student {
private int age;
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
class GereStuList {
public static List generate() {
List list = new ArrayList<>(10);
list.add(new Student(12, "张三"));
list.add(new Student(13, "朱十"));
list.add(new Student(14, "石二"));
list.add(new Student(15, "谢九"));
list.add(new Student(16, "何八"));
list.add(new Student(17, "刘七"));
list.add(new Student(18, "郑一"));
list.add(new Student(19, "赵六"));
list.add(new Student(20, "王五"));
list.add(new Student(21, "李四"));
return list;
}
}
:演示Stream的使用:
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamTest01 {
public static void main(String[] args) {
Stream s = Stream.of(1, 2, 3, 4, 5);
// iterate生成Stream[1,2,3,4,5]
Stream s0 = Stream.iterate(1, i -> i + 1).limit(5);
s0.forEach(System.out::println);
List list = GereStuList.generate();
// 将list中的Student按年龄大于等于15的,升序排列,打印
// 调用compare中的排序方法comparing自然排序
list.stream().filter(x -> x.getAge() >= 15).sorted(Comparator.comparing(Student::getAge))
.forEach(x -> System.out.println(x));
// 将list中的Student年龄小于15的,降序排列打印
// 调用Integer中的compare方法
list.stream().filter(x -> x.getAge() < 15).sorted((s1, s2) -> Integer.compare(s2.getAge(), s1.getAge()))
.forEach(System.out::println);
// 计算list中年龄小于16的元素的个数
long count = list.stream().filter(x -> x.getAge() < 16).count();
System.out.println(count);
// 取出每个人的年龄,加1后返回成List
List list2 = list.stream().map(x -> x.getAge()).map(i -> i + 1).collect(Collectors.toList());
list2.forEach(System.out::println);
// 获取List中每个人的名字,返回成一个List
list2 = list.stream().map(x -> x.getName()).collect(Collectors.toList());
list2.forEach(System.out::println);
// 计算list中大于16的人的年龄之和
Optional sum = list.stream().filter(x -> x.getAge() > 16).map(x -> x.getAge()).reduce((x, y) -> x + y);
System.out.println(sum);
// 将list中大于16的人的年龄各减1,再计算他们的年龄之和
int sum2 = list.stream().filter(x -> x.getAge() > 16).map(x -> x.getAge() - 1).reduce(0, (x, y) -> x + y);
System.out.println(sum2);
// 返回最大年龄和最小年龄
Optional o1 = list.stream().map(x -> x.getAge()).max((x, y) -> Integer.compare(x, y));
System.out.println(o1);
o1 = list.stream().map(x -> x.getAge()).max((x, y) -> Integer.compare(y, x));
System.out.println(o1);
// 计算最大年龄和最小年龄
Optional o2 = list.stream().map(x -> x.getAge()).reduce((x, y) -> Integer.max(x, y));
System.out.println(o2);
o2 = list.stream().map(x -> x.getAge()).reduce(Integer::min);// 使用了Integer中的min方法
System.out.print(o2);
}
}
演示IntStream的使用:
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.stream.IntStream;
public class IntStreamTest02 {
public static void main(String[] args) {
List list = GereStuList.generate();
// 将stream流中的学生年龄抽取出来转换为IntStream流,并计算所有学生年龄之和
int i1 = list.stream().mapToInt(Student::getAge).sum();
System.out.println(i1);
int i2 = list.stream().mapToInt(x -> x.getAge()).sum();
System.out.println(i2);
// 计算学生平均年龄
OptionalDouble ave = list.stream().mapToInt(x -> x.getAge()).average();
System.out.println(ave);
// 计算学生中年龄最大的值
OptionalInt max = list.stream().mapToInt(x -> x.getAge()).max();
System.out.println(max);
// 生成0-50之间的数,包括50
IntStream is = IntStream.rangeClosed(0, 50);
is.forEach(System.out::println);
// 计算0-52之间(不包括52)能被3整除的元素个数
long count = IntStream.range(0, 52).filter(i -> i % 3 == 0).count();
System.out.println(count);
}
}
optional示例:
import java.util.List;
import java.util.Optional;
import stream.Student;
public class OptionalTest01 {
public static void main(String[] args) {
List list = GenerateStudentList.generate();
// 计算学生中年龄大于30的人的年龄之和
Optional op = list.stream().filter(x -> x.getAge() > 30).map(x -> x.getAge()).reduce((x, y) -> x + y);
System.out.println(op);// 打印出了Optional.empty,我们知道list中的学生年龄没有大于30的
System.out.println(op.orElse(0));// 打印出了0
Student s1 = new Student(10, "张三丰");
s1 = null;
// 现在我们知道s1的指向为空,如果直接调用其方法,肯定会报空指针异常
Optional stuop = Optional.ofNullable(s1);
System.out.println(stuop);// 打印出Optional.empty
// 调用Optional重新的ifPresent方法,如果值存在,就对其处理
stuop.ifPresent(x -> System.out.println(x.getAge()));// 因为没有值存在,什么也不做
// 如果不设置泛型,使用orElse方法时不会要求传入指定类型的值,Object类型就可以了,但Optional方法中也不能使用该指定类型的值
System.out.println(stuop.orElse(new Student(50, "小二黑")));
// 再来看个字符串
String s2 = "hello";
s1 = null;
Optional op2 = Optional.ofNullable(s1);
System.out.println(op2.orElse(15));
}
}