jdk8新特性Stream API

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

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

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

目录

Stream类 

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

匹配方法:

创建流的方法

工具方法

map和reduce

收集方法

IntStream接口   

Optional类

OptionalInt类

OptionalDouble类

OptionalLong类

使用示例


Stream类 

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

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

static<T> Stream<T> of(T... values)

如Stream<String> 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 <T> Stream<T> iterate(T seed, UnaryOperator<T> 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<Integer> list=new ArrayList<>(10);   Stream s=list.stream();

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

下面介绍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 <T> Stream.Builder<T> builder() 创建一个空的Stream.Builder流对象,可通过add方法添加元素,再通过StreamBuilder接口的build方法返回一个Stream类型的对象

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

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

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


工具方法


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

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

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

map和reduce

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

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<T> reduce(BinaryOperator<T> accumulator) 根据指定计算方法对流中所有元素计算,首先accumulator前两个元素,第三个元素再与前两个元素的计算记过accumulator,返回Optional类型

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

void forEach(Consumer<? super T> action)  循环遍历


收集方法


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

<R,A> R collect(Collector<? super T,A,R> collector) 将流中所有元素收集到集合或者Map中

<R>R   collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> 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 <T> Optional<T> empty() 创建一个空的Optional实例

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

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

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

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

Optional<T> filter(Predicate<? super T> predicate) 如果Optionla对象的值存在,根据指定规则处理后返回Optional实例,值不存在就返回空的Optional实例
boolean isPresent() 判断值是否存在
<U> Optional<U> map(Function<? super T,? extends U> 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<Student> 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<Student> 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<Student> 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<Student> 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<Student> 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));

	}
}

猜你喜欢

转载自blog.csdn.net/sinat_41132860/article/details/84644807