jdk8新特性Stream API

jdk8中新加入流Stream接口,主要为处理集合提供了便利,jdk8以后,在集合接口中新增加了默认的sream方法,用来生成流 对象结合Collection的源码增加的stream方法如下:

default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }

Stream可以看做是将流中的元素当作流水线上的产品来处理,比如一条传送履带,上面一个个元素传过来,进行处理 

目录

Stream类 

常用的四种创建流的方式:

匹配方法:

创建流的方法

工具方法

map和reduce

收集方法

IntStream接口   

Optional类

OptionalInt类

OptionalDouble类

OptionalLong类

使用示例


Stream类 

常用的四种创建流的方式:

1使用静态的of方法创建流

static Stream of(T... values)

如Stream str = Stream.of("i","love","this","game");

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 iterate(T seed, UnaryOperator f)指定一个常量seed,产生从seed到常量f(由UnaryOperator指定方法得到)的流。这是一个无限迭代的过程。可以使用Stream的limit(long maxValue)方法指定需要的个数

例如:Stream s=Stream.iterate(1,i->i+1),返回一个i+1的流,1,2,3,.....

4通过集合的stream方法创建

因为Stream的增加主要是简化了集合的操作,所以集合的实现类肯定有Stream方法了

用法如下 

List list=new ArrayList<>(10);   Stream s=list.stream();

如果集合中全是某一个类型的元素,创建集合的时候最好传入泛型,不然换成流后在流的方法中不能调用该类型的方法,因为流也不知道这种元素的类型是什么

下面介绍Stream类的常用方法:

匹配方法:

boolean allMatch(Predicate predicate) 返回是否所有元素都匹配过滤条件predicate,全部符合,返回true,否则false
boolean anyMatch(Predicate predicate) 只要有一个元素复合传入的匹配条件,返回true,全不复合,返回false

boolean noneMatch(Predicate predicate) 判断是否所有元素都不匹配指定规则,都不匹配返回true

创建流的方法

static Stream.Builder builder() 创建一个空的Stream.Builder流对象,可通过add方法添加元素,再通过StreamBuilder接口的build方法返回一个Stream类型的对象

static Stream empty() 返回一个空的Stream
static Stream iterate(T seed, UnaryOperator f) ,通过指定seed值和指定方法生成限流,例如seed,f(seed),f(f(seed)),每次都嵌套上一次的值

static Stream generate(Supplier s) 根据指定方法生成无限流,一般iterate和generate生成无限流,再配合limit方法可生成指定规则指定个数元素的流

static Stream of(T... values) ,静态方法,根据给定可变参数生成流对象
static Stream of(T t) 生成单个元素的流对象


工具方法


static Stream concat(Stream a, Stream b) 将第一个流的元素和第二个流的元素拼接 
Optional max(Comparator comparator) 根据指定比较器返回流中最大值,为Optional类型
Optional min(Comparator comparator) 根据指定比较器返回流中最小值,为Optional类型
Stream skip(long n) 跳过前n个元素,将后面的元素生成新的流. 
Stream sorted() 按自然排序(升序)对流中每个元素进行排序后生成排序后的流
Stream sorted(Comparator comparator) 根据指定比较器进行排序,然后生成排序后的流,Comparator接口有实现的comparing方法,自然升序,如需降序,可以使用Comparator接口的reversed()方法将comparing之后的结果反转,也可以重写compare方法,或者调用Integer或者String等类的compare方法,或者自己重写

Stream filter(Predicate predicate) 根据指定规则过滤元素,通过规则的元素留下来生成新的Stream

Stream limit(long maxSize) 指定要流的前maxSize个元素生成新的流
long count()  返回流中所有元素的个数 返回值为long类型
Stream distinct()  找出流中相同的元素,并将重复元素过滤掉,就是去重,返回新的Stream

map和reduce

Stream map(Function mapper) 将流中每个元素经过指定方法或者改造后,重新生成一个新的流返回

IntStream mapToInt(ToIntFunction mapper)将Stream中的元素通过指定方法后转换为IntStream流,

DoubleStream mapToDouble(ToDoubleFunction mapper)将Stream中的元素通过指定方法后转换为DoubleStream流

LongStream flatMapToLong(Function mapper)将Stream中的元素通过指定方法后转换为LongStream流
 Optional reduce(BinaryOperator accumulator) 根据指定计算方法对流中所有元素计算,首先accumulator前两个元素,第三个元素再与前两个元素的计算记过accumulator,返回Optional类型

Stream flatMap(Function> mapper) 将一个流中的每个元素都转成一个流,然后再将这些流扁平化成为一个流

void forEach(Consumer action)  循环遍历


收集方法


Object[] toArray()  生成一个包含流中所有元素的数组

R collect(Collector collector) 将流中所有元素收集到集合或者Map中

R   collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) ,经过计算后再收集
上面提到collect方法需要的参数是Collector接口类型的,Collector是一个收集器,专门为collect方法设计,如果在API中没找到的方法,基本在collect方法都可以实现,Collectors是一个工具类,提供了很多静态方法,可以将Stream转换为集合或Map(容器中的Map)

比如collect(Collectors.toList)将Stream转换为List

 

IntStream接口   

在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

Optional类

java.util.Optional Optinal类主要是防止出现空指针异常,省去了非空指针判断

常用方法:使用Optional时,跟Stream一样,如果没指定泛型,则在Optional的方法中不能直接使用该类的方法,因为它不能自动识别值属于哪个类

static Optional empty() 创建一个空的Optional实例

static Optional ofNullable(T value) 若value不为null,创建Optional实例,否则创建空实例

static Optional of(T value)  根据指定非空值创建Optional对象,最好配合orElse()方法使用

T orElse(T other)如果Optional对象的值存在,返回值,如果不存在,为空,则返回指定值

T get() 得到optional对象的值
void ifPresent(Consumer consumer) 如果Optional对象的值存在,根据消费者接口的方法处理,如不存在,什么也不做

Optional filter(Predicate predicate) 如果Optionla对象的值存在,根据指定规则处理后返回Optional实例,值不存在就返回空的Optional实例
boolean isPresent() 判断值是否存在
Optional map(Function mapper) 存过值存在,对齐处理,如果处理后的结果存在返回Optional实例

OptionalInt类

int getAsInt()得到optinalInt类型的值

OptionalDouble类

double getAsDouble()得到optinalDouble类型的值

OptionalLong类

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));

	}
}

 

 

你可能感兴趣的:(JavaSE)