http1xstream.java_java8中的Stream API

# java8中的Stream API

参考这篇文章: [http://ifeve.com/stream/](http://ifeve.com/stream/),里面的图片真的非常形象

## 1.Stream通用语法

![](https://box.kancloud.cn/8fd1da5ae07e8dde7607282a835a2255_733x186.jpg)

## 2.创建Stream

``` java

//1.Stream.of生成流

Stream stream1 = Stream.of(1, 2, 3, 4);

//2.Arrays.asList

Stream stream2 = Arrays.asList(1, 2, 3, 4).stream();

//3.Arrays.stream

Stream stream3 = Arrays.stream(new String[]{"1", "2", "3", "4"});

//4.Stream.generate 没有入参,会生成一个无限长度的流,相当于"无中生有",经常配合limit来使用

Stream stream4 = Stream.generate(() -> new Random().nextInt(5));

//5.Stream.iterate 根据传入参数迭代生成无限长度流,经常配合limit来使用

Stream stream5 = Stream.iterate(1, x -> x + 1);

```

## 3.转换Stream

- **map**: 数据类型转换

![](https://box.kancloud.cn/45bfb0b113eb909a45552d53ea632c3e_403x202.jpg)

``` java

List list = Stream.of(1, null, 2, null).map(num -> num == null ? 0 : num).collect(Collectors.toList());

System.out.println(list);//[1, 0, 2, 0]

```

- **filter**:过滤掉不符合条件的元素

![](https://box.kancloud.cn/7e4f2635a9cc78b0be962f3fed2367ea_403x206.jpg)

``` java

List list = Stream.of(1, null, 2, null).filter(num -> num != null).collect(Collectors.toList());

System.out.println(list); //[1, 2]

```

- **distinct**: 元素去重

![](https://box.kancloud.cn/7ab402185cf73cb7de61df2ce13fd290_403x205.jpg)

``` java

List list = Stream.of(1, 1, 2, 2, 3, 4).distinct().collect(Collectors.toList());

System.out.println(list); //[1, 2, 3, 4]

```

- **peek**: 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数

![](https://box.kancloud.cn/0ed60dee09675e7632898a067c11ebce_403x212.jpg)

以前一直不懂peek存在的意义在哪里,后来看api里面有段话就明白了:

``` java

//This method exists mainly to support debugging,

// where you want to see the elements as they flow past a certain point in a pipeline:

Stream.of("one", "two", "three", "four")

.filter(e -> e.length() > 3)

.peek(e -> System.out.println("Filtered value: " + e))

.map(String::toUpperCase)

.peek(e -> System.out.println("Mapped value: " + e))

.collect(Collectors.toList());

```

```

Filtered value: three

Mapped value: THREE

Filtered value: four

Mapped value: FOUR

```

简而言之,peek主要用来调试。

需要注意的是,如果没有聚合操作,peek是不会触发的,比如下面这段就不会有任何输出

``` java

Stream.of("one", "two", "three", "four")

.filter(e -> e.length() > 3)

.peek(e -> System.out.println("Filtered value: " + e))

.map(String::toUpperCase)

.peek(e -> System.out.println("Mapped value: " + e));

```

- **skip**: 丢弃Stream前N个元素

![](https://box.kancloud.cn/92d7a8090edc21fe2efb06587410fd37_403x205.jpg)

``` java

List list = Stream.of(1, 2, 3, 4).skip(2).collect(Collectors.toList());

System.out.println(list);//[3, 4]

```

- **limit**: 对Stream进行截断操作, 获取前N个元素

![](https://box.kancloud.cn/34b157bfe63221fe7bc78c10605894db_403x205.jpg)

``` java

List list = Stream.of(1, 2, 3, 4).limit(2).collect(Collectors.toList());

System.out.println(list);//[1, 2]

```

- **flatMap**: 将Stream里面的元素进行数据整合,最终这些元素会放到一条新的数据流中

![](https://box.kancloud.cn/6d61a677e30e8092284c64c0814a7e2f_1224x808.jpg)

``` java

public static void main(String... args) throws InterruptedException {

List list1 = Arrays.asList("123", "234", "345");

List list2 = Arrays.asList("abc", "bcd", "cde");

List> list = Arrays.asList(list1, list2);

List collect = list.stream().flatMap(a -> a.stream()).collect(Collectors.toList());

System.out.println(collect);//[123, 234, 345, abc, bcd, cde]

}

```

## 4.聚合

``` java

public static void main(String... args) throws InterruptedException {

//数据初始化

List list = Arrays.asList(new User("张三", "男", 15), new User("李四", "女", 20), new User("王五", "男", 15));

//1.Collectors.toList() 重新返回列表

List list1 = list.stream().map(User::getName).collect(Collectors.toList());

//2.Collectors.groupingBy() 根据指定字段分组

Map> userMap = list.stream().collect(Collectors.groupingBy(User::getSex));

//3.选中两个字段生成map

Map nameSexMap = list.stream().collect(Collectors.toMap(User::getName, User::getSex));

//4.Collectors.joining 将对象拼成字符串

String nameStr = list.stream().map(User::getName).collect(Collectors.joining(","));

//5.Collectors.toSet 转成set

Set nameSet = list.stream().map(User::getName).collect(Collectors.toSet());

//6.Collectors.partitioningBy 根据条件将对象分词两个组

Map> sexMap = list.stream().collect(Collectors.partitioningBy(user -> "男".equals(user.getSex())));

//7.count() 数量统计

long count = list.stream().count();

//8.Collectors.reducing() reduce操作,给定初始值,两两计算,得到的结果作为后面的初始值

Integer totalAge = list.stream().map(User::getAge).collect(Collectors.reducing(0, (subtotal, age) -> (subtotal + age)));

//9.Collectors.summingInt 数据汇总

Integer sumAge = list.stream().collect(Collectors.summingInt(User::getAge));

//10.Collectors.mapping 配合groupingBy使用,可以对groupingBy生成的list再进行一次聚合

Map> collect = list.stream().collect(Collectors.groupingBy(User::getSex, Collectors.mapping(User::getName, Collectors.toSet())));

//11.max 获取最大值

User user = list.stream().max(Comparator.comparingInt(User::getAge)).get();

}

}

class User {

private String name;

private String sex;

private int age;

public User(String name, String sex, int age) {

this.name = name;

this.sex = sex;

this.age = age;

}

//getter && setter

}

```

## 5.demo

``` java

class User {

private Integer age;

private String name;

private Double salary;

private String sex;

public User(String name, Integer age, Double salary,String sex) {

this.name = name;

this.age = age;

this.salary = salary;

this.sex = sex;

}

// getter setter

}

List userList = Arrays.asList(

new User("张三", 12, 6000d, "男"),

new User("李四", 28, 12000d, "男"),

new User("王五", 8, 4500d, "男"),

new User("阿西吧", null, 3000d, "女"));

```

### 1.从对象列表提取某个字段

``` java

List nameList = userList.stream()

.map(User::getName)

.collect(Collectors.toList());

System.out.println(nameList);

```

```

[张三, 李四, 王五, 阿西吧]

```

### 2.从对象列表提取某个字段,并且用分隔符连接

``` java

String nameStr = userList.stream()

.map(User::getName)

.collect(Collectors.joining(","));

System.out.println(nameStr);

```

```

张三,李四,王五,阿西吧

```

### 3.汇总某个字段

``` java

Double sumSalary = userList.stream()

.filter(user -> user.getSalary() != null)

.collect(Collectors.summingDouble(User::getSalary));

System.out.println(sumSalary);

```

```

25500.0

```

### 4.按照某个字段分组

``` java

Map> map = userList.stream().collect(Collectors.groupingBy(User::getSex));

System.out.println(JSONObject.toJSONString(map));

```

```

{

"女": [

{

"name": "阿西吧",

"salary": 3000.0,

"sex": "女"

}

],

"男": [

{

"age": 12,

"name": "张三",

"salary": 6000.0,

"sex": "男"

},

{

"age": 28,

"name": "李四",

"salary": 12000.0,

"sex": "男"

},

{

"age": 8,

"name": "王五",

"salary": 4500.0,

"sex": "男"

}

]

}

```

### 5.分组汇总

``` java

Map sexSalaryMap = userList.stream()

.collect(Collectors.groupingBy(User::getSex, Collectors.summingDouble(User::getSalary)));

System.out.println(JSONObject.toJSONString(sexSalaryMap));

```

```

{"女":3000.0,"男":22500.0}

```

### 6.统计list中数据重复出现的次数

``` java

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 2, 3, 5, 1, 1, 1, 7, 2);

Map countMap = list.stream().collect(Collectors.groupingBy(num -> num, Collectors.counting()));

for (Map.Entry entry : countMap.entrySet()) {

System.out.println("数字 " + entry.getKey() + " 出现了 " + entry.getValue() + " 次");

}

```

```

数字 1 出现了 4 次

数字 2 出现了 3 次

数字 3 出现了 2 次

数字 4 出现了 1 次

数字 5 出现了 2 次

数字 6 出现了 1 次

数字 7 出现了 1 次

```

## 参考文档:

[http://ifeve.com/stream/](http://ifeve.com/stream/)

[https://www.java67.com/2016/03/how-to-use-flatmap-in-java-8-stream.html](https://www.java67.com/2016/03/how-to-use-flatmap-in-java-8-stream.html)

[https://www.baeldung.com/java-stream-reduce](https://www.baeldung.com/java-stream-reduce)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值