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 super T> predicate) 返回是否所有元素都匹配过滤条件predicate,全部符合,返回true,否则false
boolean anyMatch(Predicate super T> predicate) 只要有一个元素复合传入的匹配条件,返回true,全不复合,返回false
boolean noneMatch(Predicate super T> predicate) 判断是否所有元素都不匹配指定规则,都不匹配返回true
static
static
static
static
static
static
static
Optional
Optional
Stream
Stream
Stream
Stream
Stream
long count() 返回流中所有元素的个数 返回值为long类型
Stream
IntStream mapToInt(ToIntFunction super T> mapper)将Stream中的元素通过指定方法后转换为IntStream流,
DoubleStream mapToDouble(ToDoubleFunction super T> mapper)将Stream中的元素通过指定方法后转换为DoubleStream流
LongStream flatMapToLong(Function super T, ? extends LongStream> mapper)将Stream中的元素通过指定方法后转换为LongStream流
Optional
void forEach(Consumer super T> 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 super T> consumer) 如果Optional对象的值存在,根据消费者接口的方法处理,如不存在,什么也不做
Optional
boolean isPresent() 判断值是否存在
Optional map(Function super T,? extends U> 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));
}
}