//使用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);
我就直接用使用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 super T> 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 super T, A, R> 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 super T, ? extends K> keyMapper,Function super T, ? extends U> 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 super T> 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 super T, ? extends K> 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的一些常用用法今天就先写到这里了,这些在我们平常开发中已经够用了