streamset 数据合并_JAVA.Stream函数,优雅的数据流操作

本文详细介绍了Java Stream API的使用,包括流的创建、数据操作、终止操作和并发处理。讲解了filter、map、peek、distinct、sorted等方法,以及流的聚合操作如reduce、collect,并展示了如何与CompletableFuture和线程池配合进行并发处理。通过实例展示了Stream在处理集合数据时的灵活性和高效性。

前言

平时操作集合数据,我们一般都是for或者iterator去遍历,不是很好看。java提供了Stream的概念,它可以让我们把集合数据当做一个个元素在处理,并且提供多线程模式流的创建

流的各种数据操作

流的终止操作

流的聚合处理

并发流和CompletableFuture的配合使用

1 stream的构造方式

stream内置的构造方法public static Stream iterate(final T seed, final UnaryOperator f)

public static Stream concat(Stream extends T> a, Stream extends T> b)

public static Builder builder()

public static Stream of(T t)

public static Stream empty()

public static Stream generate(Supplier s) 复制代码

Collection声明的stream函数default Stream stream() 复制代码Collection声明了stream转化函数,也就是说,任意Collection子类都存在官方替我们实现的由Collection转为Stream的方法示例,List转Streampublic static void main(String[] args){

List demo = Arrays.asList("a","b","c");

long count = demo.stream().peek(System.out::println).count();

System.out.println(count);

}

-------result--------

a

b

c

3

复制代码

2 接口stream对元素的操作方法定义

过滤 filterStream filter(Predicate super T> predicate) 复制代码Predicate是函数式接口,可以直接用lambda代替;如果有复杂的过滤逻辑,则用or、and、negate方法组合

示例List demo = Arrays.asList("a", "b", "c");

Predicate f1 = item -> item.equals("a");

Predicate f2 = item -> item.equals("b");

demo.stream().filter(f1.or(f2)).forEach(System.out::println);

-------result--------

a

b

复制代码

映射转化 map Stream map(Function super T, ? extends R> mapper)

IntStream mapToInt(ToIntFunction super T> mapper);

LongStream mapToLong(ToLongFunction super T> mapper);

DoubleStream mapToDouble(ToDoubleFunction super T> mapper);

复制代码示例static class User{

public User(Integer id){this.id = id; }

Integer id; public Integer getId() { return id; }

}

public static void main(String[] args) {

List demo = Arrays.asList(new User(1), new User(2), new User(3));

// User 转为 Integer(id)

demo.stream().map(User::getId).forEach(System.out::println);

}

-------result--------

1

2

3

复制代码

数据处理 peekStream peek(Consumer super T> action);

复制代码与map的区别是其无返回值

示例static class User{

public User(Integer id){this.id = id; }

Integer id;

public Integer getId() { return id; }

public void setId(Integer id) { this.id = id; }

}

public static void main(String[] args) {

List demo = Arrays.asList(new User(1), new User(2), new User(3));

// id平方,User 转为 Integer(id)

demo.stream().peek(user -> user.setId(user.id * user.id)).map(User::getId).forEach(System.out::println);

}

-------result--------

1

4

9

复制代码

映射撵平 flatMap Stream flatMap(Function super T, ? extends Stream extends R>> mapper);

IntStream flatMapToInt(Function super T, ? extends IntStream> mapper);

LongStream flatMapToLong(Function super T, ? extends LongStream> mapper);

DoubleStream flatMapToDouble(Function super T, ? extends DoubleStream> mapper);

复制代码flatMap:将元素为Stream类型的流撵平成一个元素类型为T的Stream流

示例public static void main(String[] args) {

List> demo = Arrays.asList(Stream.of(5), Stream.of(2), Stream.of(1));

demo.stream().flatMap(Function.identity()).forEach(System.out::println);

}

-------result--------

5

2

1

复制代码

去重 distinctStream distinct();

复制代码示例List demo = Arrays.asList(1, 1, 2);

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

-------result--------

1

2

复制代码

排序 sortedStream sorted();

Stream sorted(Comparator super T> comparator);

复制代码示例List demo = Arrays.asList(5, 1, 2);

//默认升序

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

//降序

Comparator comparator = Comparator.comparing(item -> item).reversed();

demo.stream().sorted(comparator).forEach(System.out::println);

-------默认升序 result--------

1

2

5

-------降序 result--------

5

2

1

复制代码

个数限制limit和跳过skip//截取前maxSize个元素

Stream limit(long maxSize);

//跳过前n个流

Stream skip(long n);

复制代码示例List demo = Arrays.asList(1, 2, 3, 4, 5, 6);

//跳过前两个,然后限制截取两个

demo.stream().skip(2).limit(2).forEach(System.out::println);

-------result--------

3

4

复制代码

JDK9提供的新操作和filter的区别,takeWhile是取满足条件的元素,直到不满足为止;dropWhile是丢弃满足条件的元素,直到不满足为止default Stream takeWhile(Predicate super T> predicate);

default Stream dropWhile(Predicate super T> predicate);

复制代码

3 stream的终止操作action

遍历消费//遍历消费

void forEach(Consumer super T> action);

//顺序遍历消费,和forEach的区别是forEachOrdered在多线程parallelStream执行,其顺序也不会乱

void forEachOrdered(Consumer super T> action);

复制代码示例List demo = Arrays.asList(1, 2, 3);

demo.parallelStream().forEach(System.out::println);

demo.parallelStream().forEachOrdered(System.out::println);

-------forEach result--------

2

3

1

-------forEachOrdered result--------

1

2

3

复制代码

获取数组结果//流转成Object数组

Object[] toArray();

//流转成A[]数组,指定类型A

A[] toArray(IntFunction generator)

复制代码示例List demo = Arrays.asList("1", "2", "3");

// A[] toArray(IntFunction generator)

String[] data = demo.stream().toArray(String[]::new);

复制代码

最大最小值//获取最小值

Optional min(Comparator super T> comparator)

//获取最大值

Optional max(Comparator super T> comparator) 复制代码示例List demo = Arrays.asList(1, 2, 3);

Optional min = demo.stream().min(Comparator.comparing(item->item));

Optional max = demo.stream().max(Comparator.comparing(item->item));

System.out.println(min.get()+"-"+max.get());

-------result--------

1-3

复制代码

查找匹配//任意一个匹配

boolean anyMatch(Predicate super T> predicate)

//全部匹配

boolean allMatch(Predicate super T> predicate)

//不匹配

boolean noneMatch(Predicate super T> predicate)

//查找第一个

Optional findFirst();

//任意一个

Optional findAny();

复制代码

归约合并//两两合并

Optional reduce(BinaryOperator accumulator)

//两两合并,带初始值的

T reduce(T identity, BinaryOperator accumulator)

//先转化元素类型再两两合并,带初始值的

U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) 复制代码示例List demo = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);

//数字转化为字符串,然后使用“-”拼接起来

String data = demo.stream().reduce("0", (u, t) -> u + "-" + t, (s1, s2) -> s1 + "-" + s2);

System.out.println(data);

-------result--------

0-1-2-3-4-5-6-7-8

复制代码

计算元素个数long count() 复制代码示例List demo = Arrays.asList(1, 2, 3, 4, 5, 6);

System.out.println(demo.stream().count());

-------result--------

6

复制代码

对流的聚合处理/**

* supplier:返回结果类型的生产者

* accumulator:元素消费者(处理并加入R)

* combiner: 返回结果 R 怎么组合(多线程执行时,会产生多个返回值R,需要合并)

*/

R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner);

/**

* collector一般是由 supplier、accumulator、combiner、finisher、characteristics组合成的聚合类

* Collectors 可提供一些内置的聚合类或者方法

*/

R collect(Collector super T, A, R> collector);

复制代码示例,看下面

4 Collector(聚合类)的工具类集Collectors

接口Collector和实现类CollectorImpl//返回值类型的生产者

Supplier supplier();

//流元素消费者

BiConsumer accumulator();

//返回值合并器(多个线程操作时,会产生多个返回值,需要合并)

BinaryOperator combiner();

//返回值转化器(最后一步处理,实际返回结果,一般原样返回)

Function finisher();

//流的特性

Set characteristics();

public static Collector of(Supplier supplier,

BiConsumer accumulator, BinaryOperator combiner,

Function finisher, Characteristics... characteristics) 复制代码

流聚合转换成List, Set//流转化成List

public static Collector> toList()

//流转化成Set

public static Collector> toSet()

复制代码示例List demo = Arrays.asList(1, 2, 3);

List col = demo.stream().collect(Collectors.toList());

Set set = demo.stream().collect(Collectors.toSet());

复制代码

流聚合转化成Map//流转化成Map

public static Collector> toMap(

Function super T, ? extends K> keyMapper,

Function super T, ? extends U> valueMapper)

/**

* mergeFunction:相同的key,值怎么合并

*/

public static Collector> toMap(

Function super T, ? extends K> keyMapper,

Function super T, ? extends U> valueMapper,

BinaryOperator mergeFunction)

/**

* mergeFunction:相同的key,值怎么合并

* mapSupplier:返回值Map的生产者

*/

public static > Collector toMap(

Function super T, ? extends K> keyMapper,

Function super T, ? extends U> valueMapper,

BinaryOperator mergeFunction,

Supplier mapSupplier)

复制代码如果存在相同key的元素,会报错;或者使用groupBy

示例List demo = Arrays.asList(new User(1), new User(2), new User(3));

Map map = demo.stream().collect(Collectors.toMap(User::getId,item->item));

System.out.println(map);

-------result-------

{1=TestS$User@7b23ec81, 2=TestS$User@6acbcfc0, 3=TestS$User@5f184fc6}

复制代码

字符串流聚合拼接//多个字符串拼接成一个字符串

public static Collector joining();

//多个字符串拼接成一个字符串(指定分隔符)

public static Collector joining(CharSequence delimiter)

复制代码示例List demo = Arrays.asList("c", "s", "c","w","潜行前行");

String name = demo.stream().collect(Collectors.joining("-"));

System.out.println(name);

-------result-------

c-s-c-w-潜行前行

复制代码

映射处理再聚合流相当于先map再collect/**

* mapper:映射处理器

* downstream:映射处理后需要再次聚合处理

*/

public static Collector mapping(Function super T, ? extends U> mapper,

Collector super U, A, R> downstream);

复制代码示例List demo = Arrays.asList("1", "2", "3");

List data = demo.stream().collect(Collectors.mapping(Integer::valueOf, Collectors.toList()));

System.out.println(data);

-------result-------

[1, 2, 3]

复制代码

聚合后再转换结果/**

* downstream:聚合处理

* finisher:结果转换处理

*/

public static Collector collectingAndThen(Collector downstream,

Function finisher);

复制代码示例List demo = Arrays.asList(1, 2, 3, 4, 5, 6);

//聚合成List,最后提取数组的size作为返回值

Integer size = demo.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));

System.out.println(size);

---------result----------

6

复制代码

流分组(Map是HashMap)/**

* classifier 指定T类型某一属性作为Key值分组

* 分组后,使用List作为每个流的容器

*/

public static Collector>> groupingBy(

Function super T, ? extends K> classifier);

/**

* classifier: 流分组器

* downstream: 每组流的聚合处理器

*/

public static Collector> groupingBy(

Function super T, ? extends K> classifier,

Collector super T, A, D> downstream)

/**

* classifier: 流分组器

* mapFactory: 返回值map的工厂(Map的子类)

* downstream: 每组流的聚合处理器

*/

public static > Collector groupingBy(

Function super T, ? extends K> classifier,

Supplier mapFactory,

Collector super T, A, D> downstream)

复制代码示例public static void main(String[] args) throws Exception {

List demo = Stream.iterate(0, item -> item + 1)

.limit(15)

.collect(Collectors.toList());

// 分成三组,并且每组元素转化为String类型

Map> map = demo.stream()

.collect(Collectors.groupingBy(item -> item % 3,

HashMap::new,

Collectors.mapping(String::valueOf, Collectors.toList())));

System.out.println(map);

}

---------result----------

{0=[0, 3, 6, 9, 12], 1=[1, 4, 7, 10, 13], 2=[2, 5, 8, 11, 14]}

复制代码

流分组(分组使用的Map是ConcurrentHashMap)/**

* classifier: 分组器 ; 分组后,使用List作为每个流的容器

*/

public static Collector>> groupingByConcurrent(

Function super T, ? extends K> classifier);

/**

* classifier: 分组器

* downstream: 流的聚合处理器

*/

public static Collector> groupingByConcurrent(

Function super T, ? extends K> classifier, Collector super T, A, D> downstream)

/**

* classifier: 分组器

* mapFactory: 返回值类型map的生产工厂(ConcurrentMap的子类)

* downstream: 流的聚合处理器

*/

public static > Collector groupingByConcurrent(

Function super T, ? extends K> classifier,

Supplier mapFactory,

Collector super T, A, D> downstream);

复制代码用法和groupingBy一样

拆分流,一变二(相当于特殊的groupingBy)public static Collector>> partitioningBy(

Predicate super T> predicate)

/**

* predicate: 二分器

* downstream: 流的聚合处理器

*/

public static Collector> partitioningBy(

Predicate super T> predicate, Collector super T, A, D> downstream)

复制代码示例List demo = Arrays.asList(1, 2,3,4, 5,6);

// 奇数偶数分组

Map> map = demo.stream()

.collect(Collectors.partitioningBy(item -> item % 2 == 0));

System.out.println(map);

---------result----------

{false=[1, 3, 5], true=[2, 4, 6]}

复制代码

聚合求平均值// 返回Double类型

public static Collector averagingDouble(ToDoubleFunction super T> mapper)

// 返回Long 类型

public static Collector averagingLong(ToLongFunction super T> mapper)

//返回Int 类型

public static Collector averagingInt(ToIntFunction super T> mapper)

复制代码示例List demo = Arrays.asList(1, 2, 5);

Double data = demo.stream().collect(Collectors.averagingInt(Integer::intValue));

System.out.println(data);

---------result----------

2.6666666666666665

复制代码

流聚合查找最大最小值//最小值

public static Collector> minBy(Comparator super T> comparator)

//最大值

public static Collector> maxBy(Comparator super T> comparator)

复制代码示例List demo = Arrays.asList(1, 2, 5);

Optional min = demo.stream().collect(Collectors.minBy(Comparator.comparing(item -> item)));

Optional max = demo.stream().collect(Collectors.maxBy(Comparator.comparing(item -> item)));

System.out.println(min.get()+"-"+max.get());

---------result----------

1-5

复制代码

聚合计算统计结果可以获得元素总个数,元素累计总和,最小值,最大值,平均值//返回Int 类型

public static Collector summarizingInt(

ToIntFunction super T> mapper)

//返回Double 类型

public static Collector summarizingDouble(

ToDoubleFunction super T> mapper)

//返回Long 类型

public static Collector summarizingLong(

ToLongFunction super T> mapper)

复制代码示例List demo = Arrays.asList(1, 2, 5);

IntSummaryStatistics data = demo.stream().collect(Collectors.summarizingInt(Integer::intValue));

System.out.println(data);

---------result----------

IntSummaryStatistics{count=3, sum=8, min=1, average=2.666667, max=5}

复制代码

JDK12提供的新聚合方法//流分别经过downstream1、downstream2聚合处理,再合并两聚合结果

public static Collector teeing(

Collector super T, ?, R1> downstream1,

Collector super T, ?, R2> downstream2,

BiFunction super R1, ? super R2, R> merger)

复制代码

5 并发paralleStream的使用配合CompletableFuture和线程池的使用

示例public static void main(String[] args) throws Exception{

List demo = Stream.iterate(0, item -> item + 1)

.limit(5)

.collect(Collectors.toList());

//示例1

Stopwatch stopwatch = Stopwatch.createStarted(Ticker.systemTicker());

demo.stream().forEach(item -> {

try {

Thread.sleep(500);

System.out.println("示例1-"+Thread.currentThread().getName());

} catch (Exception e) { }

});

System.out.println("示例1-"+stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));

//示例2, 注意需要ForkJoinPool,parallelStream才会使用executor指定的线程,否则还是用默认的 ForkJoinPool.commonPool()

ExecutorService executor = new ForkJoinPool(10);

stopwatch.reset(); stopwatch.start();

CompletableFuture.runAsync(() -> demo.parallelStream().forEach(item -> {

try {

Thread.sleep(1000);

System.out.println("示例2-" + Thread.currentThread().getName());

} catch (Exception e) { }

}), executor).join();

System.out.println("示例2-"+stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));

//示例3

stopwatch.reset(); stopwatch.start();

demo.parallelStream().forEach(item -> {

try {

Thread.sleep(1000);

System.out.println("示例3-"+Thread.currentThread().getName());

} catch (Exception e) { }

});

System.out.println("示例3-"+stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));

executor.shutdown();

}

复制代码-------------------result--------------------------示例1-main

示例1-main

示例1-main

示例1-main

示例1-main

示例1-2501

示例2-ForkJoinPool-1-worker-19

示例2-ForkJoinPool-1-worker-9

示例2-ForkJoinPool-1-worker-5

示例2-ForkJoinPool-1-worker-27

示例2-ForkJoinPool-1-worker-23

示例2-1004

示例3-main

示例3-ForkJoinPool.commonPool-worker-5

示例3-ForkJoinPool.commonPool-worker-7

示例3-ForkJoinPool.commonPool-worker-9

示例3-ForkJoinPool.commonPool-worker-3

示例3-1001

复制代码parallelStream的方法确实会使用多线程去运行,并且可以指定线程池,不过自定义线程必须是ForkJoinPool类型,否则会默认使ForkJoinPool.commonPool()的线程

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值