Stream流简单操作



学了Lambda表达式之后感觉没什么用处对吧,其实不然,在流操作里面可以体验其简便性,因为平时用得少,很容易忘记


1. Stream

其在java.util.Stream包下, 提供对数据进行各种简便操作,效率当然比我们手写要好,并且支持并行操作,其使用过程分为三步:

  • 创建Stream流
  • 中间操作
  • 最终操作

是不是有点奇怪? 没关系,刚开始的时候笔者也这样觉得,后面就知道其必要性


优点:

  • stream不会进行存储
  • 对源数据不产生修改,一切操作在生成的stream上
  • stream不会立即执行,而是延迟操作,即到了最终操作才会从头到尾执行
  • stream只能使用一次,使用过后要再次生成才能使用,否则 IllegalStateException




2. 创建Stream流

还有个平行流这里不解释了(parallelStream),创建的创建流的方式:


Arrays.stream()

数组工具类有个静态方法,传入数组创建流

int[] arr = {9,5,2,7};
Arrays.stream(arr);

Stream.of()

流里也有一个静态方法,传入一个泛型数组,或多个值创建流,记得导包

Stream.of(1,2,3);

集合中创建

我们最常用集合来创建Stream流,注意不支持Map集合

new ArrayList( Arrays.asList("11111","AAAA","5") );
new HashSet().stream();




3. 中间操作

所谓的中间操作笔者是这样理解的,其方法返回值是this,没错就是返回Stream流本身,中间操作会返回一个新的流,然后再执行后面的中间操作,可以理解为过滤数据之后再进行过滤。而且这些操作是延迟执行的,即调用最终操作时才全部执行中间操作。


常见的中间操作,看名字就知道有什么作用了

  • filter() // 对传参进行判断,符合的才存回流
  • map() // 对传参进行操作 ,把操作完的数据放回流
  • distinct() // 去重基于equals 和 hashCode的,具体为什么 请看这里
  • sorted()
  • peek()
  • limit()
  • skip()

实际操作

ArrayList<String> arrayList = new ArrayList( Arrays.asList("11111","AAAA","5","6","7222","CC","211","3","FFF","zzz") );


Stream stream = arrayList.stream()
                .sorted()
                .distinct()
                .limit(10)
                .skip(1)
                .filter(s-> s.length() > 1)
                .map( s -> s + " index")
                .map( s -> s.toLowerCase())

filter其方法的参数是一个Predicate函数式接口,其接口为boolean test(T t);

map方法的参数是Function函数式接口,方法为R apply(T t),@return the function result





4. 最终操作


常见的最终操作

  • forEach()

  • toArray()

  • min()

  • max()

  • count()

  • anyMatch

  • allMatch

  • reduce:规约,可将流中元素反复结合起来,输出最终值


forEach方法的参数是一个Consumer函数式接口,接口为void accept(T t),最给定的参数T进行操作,熟悉Lambda的可能会将方法引用放进去,下面二者是相等的

stream.forEach( System.out::println );

stream.forEach( s -> System.out.println(s) );




5. 简便方法

笔者最近遇到的,立个flag,要成为Stream的忠实粉丝


数组去重

int[] arr = {1,2,3,4,5,1,1,3,10};
arr = Arrays.stream(arr).distinct().toArray();
		
for(int value : arr){
	System.out.println(value);
}
1
2
3
4
5
10

求最值

int a = Arrays.stream(arr).max().getAsInt();	// 返回Optinal类型	
System.out.println(a);
10

匹配

boolean rs = Arrays.stream(arr).anyMatch( t -> t == 10);  // 传入一个predicate
System.out.println(rs);

聚合

int sum = Arrays.stream(arr).reduce( (l,r) -> l+r ).getAsInt();
System.out.println(sum);  // 25,聚合实现总计功能,即用上一个值计算下一个值 




6. Optional

这里顺带说一下1.8的另一个新特性,优雅解决空指针异常


/**
 * @description 获取email并将其转成大写,若为空返回null
 * @author Howl
 */
public class Test {
	
	public static String getEmail(User user){
		
		return Optional.ofNullable(user)
				.map( t -> t.getEmail())
				.map( t -> t.toUpperCase())
				.orElse(null);
	}
	
	public static void main(String[] args) {
		
		User user = null;
		
		System.out.println(user.getEmail());  // 这里报错
		
		System.out.println(Test.getEmail(user));  // 这里不报错
	}
}

常用方法:

  • Optional.empty()

  • Optional.of()

  • Optional.ofNullable()

  • optional.isPresent()

  • optional.get()

  • optional.orElse()

  • optional.map

  • optional.filter



原文地址:https://www.cnblogs.com/Howlet/p/12402991.html