Stream流常用API

Stream介绍

1、Stream创建方式

	//使用Collection.stream()
	LinkedList<Integer> ids = new LinkedList<>();
	Stream<Integer> collectionStream = ids.stream();
	//使用Arrays.stream()
	IntStream arrayStream = Arrays.stream(new int[]{1, 2, 3});
	//使用Stream.of()
	Stream<Integer> valueStream = Stream.of(1, 2, 3);

2、常用APi

我就直接用使用Collection.stream()来创建Stream进行演示了,先准备个集合

	List<Integer> idsLinkedList = Lists.newLinkedList();
	idsLinkedList.add(50);
	idsLinkedList.add(30);
	idsLinkedList.add(20);
(一) 匹配操作
    //是否所有的元素都满足匹配条件
    boolean allMatchResult = idsLinkedList.stream().allMatch(e -> e >= 20);
    //是否存在任意元素满足匹配
    boolean anyMatchResult = idsLinkedList.stream().anyMatch(e -> e > 50);
    //是否所有元素都不满足匹配
    boolean noneMatchResult = idsLinkedList.stream().noneMatch(e -> e >= 60);

    System.out.println(allMatchResult + "||" + anyMatchResult + "||" + noneMatchResult);

输出:

true||false||true
(二)遍历打印

Stream也支持forEach操作,虽然有的集合本身也支持forEach

//void forEach(Consumer action)  对流中中每个元素进行action操作
idsLinkedList.stream().forEach(System.out::println);    //打印所有元素
System.out.println("======");
idsLinkedList.forEach(System.out::println);	

输出:

50
30
20
======
50
30
20

可以看出两个结果是一样的,当然,这里使用Stream.forEach()是用于演示下,在一些数据结构本身就支持forEach()的情况下,直接使用自身的会更方便。

(三)收集操作(将流中元素收集至新的数据结构)
// R collect(Collector collector)    收集流中元素
//Collectors.toMap(keyMapper, valueMapper) 第一个参数生成key值,第二个参数生成value值
Map<Integer, Integer> collectMap = idsLinkedList.stream().collect(Collectors.toMap(e -> e, e -> e/10));
System.out.println("collectMap: " + collectMap);
List<Integer> collectList = idsLinkedList.stream().collect(toList());
System.out.println("collectList: " + collectList);
Set<Integer> collectSet = idsLinkedList.stream().collect(Collectors.toSet());
System.out.println("collectSet: " + collectSet);

如果要指定的数据结构是Map类型的话,需要传递键映射器和值映射器的映射函数—即Collectors.toMaptoMap(Function keyMapper,Function valueMapper)中的keyMapper,valueMapper

输出:

collectMap: {50=5, 20=2, 30=3}
collectList: [50, 30, 20]
collectSet: [50, 20, 30]
(四)寻找操作
    //返回描述此流的第一个元素的Optional如果流为空,则返回一个空的Optional 。
    Optional<Integer> first = idsLinkedList.stream().findFirst();
    //元素是否存在
    if (first.isPresent()){
        System.out.println("流中第一个元素为:	" + first.get());
    }

    //返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional
    Optional<Integer> findAny = idsLinkedList.stream().findAny();
    if (findAny.isPresent()){
        System.out.println("findAny:	" + first.get());
    }

findFirst()是寻找流中第一个元素,findAny()是返回流中任意一个元素,两者返回的容器对象可能为空值也可能不为空值,要返回这个值的话,可以使用Optional.get()方法,但不能直接使用get()方法,需要使用isPresent()方法先看看是否存在值,存在值再输出,否则为空的话直接get()会抛出异常,可以看下源码:

    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

输出:

流中第一个元素为:	50
findAny:	50
(五)跳过元素

Stream skip(long n) 表示跳过n个元素后返回的流,如果n<0,会抛出异常,如果n=0的话,则返回流本身。

具体我们来看下源码:

@Override
    public final Stream<P_OUT> skip(long n) {
        if (n < 0)
            throw new IllegalArgumentException(Long.toString(n));
        if (n == 0)
            return this;
        else
            return SliceOps.makeRef(this, n, -1);
    }

操作:

List<Integer> skipList = idsLinkedList.stream().skip(2).collect(toList());
System.out.println("流跳过两个元素后收集得到的skipList为:   " + skipList);

输出:

流跳过两个元素后收集得到的skipList为:   [20]
(六)排序

流也支持排序,Stream.sorted(Comparator comparator)就是进行排序操作的,里面的参数是比较器,我们可以根据自己的需求自行写符合的比较器,默认是升序,比较器的用法我这里就不阐述了

List<Integer> descSortCollectList = idsLinkedList.stream().sorted((e1, e2) -> e2 -e1).collect(toList());
System.out.println("流中元素按降序排序后得到的sortCollectList:  " + descSortCollectList);

List<Integer> ascSortCollectList = idsLinkedList.stream().sorted().collect(toList());
System.out.println("流中元素按升序排序后得到的sortCollectList:  " + ascSortCollectList);

输出:

流中元素按降序排序后得到的sortCollectList:  [50, 30, 20]
流中元素按升序排序后得到的sortCollectList:  [20, 30, 50]
(七)去重操作

去重毫无疑问就是过滤掉重复出现的元素,类似于MySQL中的 distinct 关键字的作用

idsLinkedList.add(50);
List<Integer> distinctList = idsLinkedList.stream().distinct().collect(toList());
System.out.println("去重后的distinctList:   " + distinctList);

输出:

去重后的distinctList:   [50, 30, 20]

集合中原本存在50,20,30三个元素,我又给集合中添加了元素50,可以看到使用distinct()后输出的结果中,只有一个50

(八)最大值、最小值

要是想找出数据结构中的最大值、最小值,我们就不需要手动写循环,遍历每个元素,每次值进行比较这样的代码了,直接调个API就可以解决了

//返回流中的最大元素
Optional<Integer> maxOptional = idsLinkedList.stream().max(Integer::compareTo);
if (maxOptional.isPresent()) {
    System.out.println("最大值为:  " + maxOptional.get());
}
//返回流中的最小元素
Optional<Integer> minOptional = idsLinkedList.stream().min(Integer::compareTo);
if (minOptional.isPresent()){
    System.out.println("最小值为:  " + idsLinkedList.stream().min(Integer::compareTo).get());
}

输出:

最大值为:  50
最小值为:  20
(九)求和

求总和也是一样,我们不需要像之前一样写繁琐的代码,去遍历每次拿个变量记录,再和一个个元素相加这样的代码了,Stream也同样提供了API

Integer sumValue = idsLinkedList.stream().collect(Collectors.summingInt(Integer::intValue));
System.out.println("总和为:    " + sumValue);

输出:

总和为:    150
(十)平均值

同最大值、最小值、总和一样

Double averageValue = idsLinkedList.stream().collect(Collectors.averagingInt(Integer::intValue));
System.out.println("平均值为:   " + averageValue);

输出:

平均值为:   37.5
(十一)过滤

个人觉得这个操作还是非常实用的,我们可以自己写谓词(Predicate),过滤出来我们需要的数据

//流中满足匹配条件的数量
System.out.println("满足条件的count:  " + idsLinkedList.stream().filter(e -> e == 20).count());

这块儿代码的意思是,过滤出元素值等于20的数据,并求出数量,也就是说流中有几个值为20的元素

输出:

满足条件的count:  1
(十二)分组

groupingBy(Function classifier)可以对集合中的一个或多个属性进行分组

Map<Boolean, List<Integer>> groupByMap = idsLinkedList.stream().collect(Collectors.groupingBy(e -> e % 3 == 0));
System.out.println("分组后的Map:    " + groupByMap);

Map<String, List<Integer>> groupByMap01 = idsLinkedList.stream().collect(Collectors.groupingBy(e -> {
    if (e == 30) {
        return "值为30的元素";
    } else if (e == 50) {
        return "值为50的元素";
    } else if (e == 20) {
        return "值为20的元素";
    } else {
        return "";
    }
}));
System.out.println("分组后的groupByMap01:   " + groupByMap01);

输出:

分组后的Map:    {false=[50, 20, 50], true=[30]}
分组后的groupByMap01:   {值为50的元素=[50, 50], 值为20的元素=[20], 值为30的元素=[30]}

关于Stream的一些常用用法今天就先写到这里了,这些在我们平常开发中已经够用了

你可能感兴趣的:(Java基础,java)