stream流map 多个字段_Java8用了这么久了,Stream 流用法及语法你都知道吗?

1.简介

Stream流 最全的用法

Stream 能用来干什么?用来处理集合,通过 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询,Stream API 提供了一种高效且易于使用的处理数据的方式

为什么用Java 8 Stream ?因为 操作简单

为什么操作简单?因为 Lambda 表达式,它极大的提高了编程效率和程序可读性

怎么操作流? 首先你的有个数据源(数组、集合),操作会产生新的流对象,原来的流对象不会改变

流用法有结束操作,这种代码不是你写了一个方法就执行一个方法,而是最后触发结束操作的时候才统一执行的,collect、foreach 方法就是一种结束方法,详情看代码及结果参考 2.映射map、flatMap用法 部分

2.具体用法

2.1 创建流

// 集合创建流

List list = new ArrayList<>();

// 获取一个顺序流

Stream listStream = list.stream();

// 获取一个并行流

Stream parallelListStream = list.parallelStream();

// 数组创建流

Integer[] nums = new Integer[] { 1, 2, 3, 4, 5 };

Stream arrStream = Arrays.stream(nums);

arrStream.forEach(System.out::println);// 1 2 3 4 5

// 静态方法of创建流

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

ofStream.forEach(System.out::println);// 1 2 3 4 5

// 静态方法iterate 创建流

Stream iterateStream = Stream.iterate(1, (x) -> x + 10).limit(4);

iterateStream.forEach(System.out::println); // 1 11 21 31

// 静态方法generate 创建流

Stream generateStream = Stream.generate(Math::random).limit(2);

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

2.2 操作流

1.过滤

filter:过滤流中的某些元素(可以做一些基本的判空、替换、判断逻辑操作)

limit(n):获取n个元素,结果获取几个元素

skip(n):跳过n元素,配合limit(n)可实现分页

distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

//filter 判空

Stream notNullStreamObj = Stream.of(1, 2, null, 4, 5, 6, 7, null, 2);

Stream notNullStream = notNullStreamObj.filter(i -> (null != i));

notNullStream.forEach(System.out::println);//1 2 4 5 6 7 2

//filter 逻辑判断

Stream logicStreamObj = Stream.of(1, 2, null, 4, 5, 6, 7, null, 2);

Stream logicStream = logicStreamObj.filter(i -> (i != null && i > 5));

logicStream.forEach(System.out::println); // 6 7

//filter 替换

Stream strStreamObj = Stream.of("aa", "ab", null, "ac", "bd", "ee");

Stream strStream = strStreamObj.filter(str -> (null != str && str.contains("a")));

strStream.forEach(System.out::println); // aa ab ac

//skip 跳过

Stream skipStreamObj = Stream.of("aa", "ab", null, "ac", "bd", "ee");

Stream skipStream = skipStreamObj.skip(2);

skipStream.forEach(System.out::println); // null ac bd ee

//distinct 去重

Stream disStreamObj = Stream.of("aa", "ab", null, "ac", "aa", "ab", null, "ee");

Stream disStream = disStreamObj.distinct();

disStream.forEach(System.out::println); // aa ab null ac ee

2.映射

map:接收一个函数作为参数,该函数会被应用到每个元素上,映射成一个新的元素。

flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

peek:这个操作很骚,类似map只不过map 是Func函数,提供返回值,而peer是取出元素,Consumer表达式设值,我个人觉得没啥区别呢,官方文档提示:该方法主要用于调试,做一些消耗这个对象但不修改它的东西,没啥事不要用

很想问一下 这俩map、flatMap 区别 ,细品,你细品,你细细品

map是将每个元素 映射成一个新元素,除非你过滤了,否则不会改变元素个数

flatMap是将原流中的每个值都变成另一个流,然后把流合并串起来,必须有返回值,拼装成新的流

//map 把包含a的元素,替换成| 注意,注意, 元素还是一个整体,对每个元素

Stream mapStreamObj = Stream.of("a,b,c", "a,e,f", "g,h,i");

Stream mapStream = mapStreamObj.map(str -> str.replaceAll(",", "|"));

mapStream.forEach(System.out::println); // a|b|c a|e|f h|i|j

//flatMap 可以把元素 切分后,再按照新元素组成新的字符串

Stream flatMapStreamObj = Stream.of("a,b,c", "a,e,f", "g,h,i");

Stream flatMapStream = flatMapStreamObj.flatMap(str -> {

String[] arr = str.split(",");

Stream result = Arrays.stream(arr);

return result;

});

flatMapStream.forEach(System.out::println); //a b c d e f g h i

System.out.println("1===========");

Stream peekStreamObj = Stream.of("a,b,c", "a,e,f", "g,h,i");

Stream peekStream = peekStreamObj.peek(e -> System.out.println("Filtered value: " + e))

.map(String::toUpperCase)

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

System.out.println("2=========== peek代码结束,但是日志没打印");

Set stringSet = peekStream.collect(Collectors.toSet());

System.out.println("3=========== collect结束操作,代码日志打印");

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

map执行结果

//看下执行结果,说明 collect才是结束操作,代码结束,但是并不是真正结束

1===========

2=========== peek代码结束,但是日志没打印

Filtered value: a,b,c

Mapped value: A,B,C

Filtered value: a,e,f

Mapped value: A,E,F

Filtered value: g,h,i

Mapped value: G,H,I

3=========== collect结束操作,代码日志打印

A,B,C

A,E,F

G,H,I

3.排序

sorted():自然排序,流中元素需实现Comparable接口

sorted(Comparator com):定制排序,自定义Comparator排序器

先构建一个User类

public static class User {

private String name;

private Integer age;

public User(String name, Integer age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

@Override

public String toString() {

return "User{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

然后 看下sort用法

//按字母排序

Stream sortStreamObj = Stream.of("a,e,f", "a,d,c", "a,b,i");

Stream sortStream = sortStreamObj.sorted();

sortStream.forEach(System.out::println); //abi adc aef

User u1 = new User("bb", 1);

User u2 = new User("aa", 2);

User u3 = new User("cc", 3);

User u4 = new User("aa", 4);

Set userSet = Sets.newHashSet(u1, u2, u3, u4);

Stream userStream = userSet.stream().sorted(

(obj1, obj2) -> {

if (obj1.getName().equals(obj2.getName())) {

//name相等 按age

return obj1.getAge() - obj2.getAge();

}

return obj1.getName().compareTo(obj2.getName());

}

);

userStream.forEach(System.out::println);// u2 u4 u1 u3

sort 执行结果

a,b,i

a,d,c

a,e,f

User{name='aa', age=2}

User{name='aa', age=4}

User{name='bb', age=1}

User{name='cc', age=3}

4.流匹配

allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false

noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false

anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false

findFirst:返回流中第一个元素

findAny:返回流中的任意元素

count:返回流中元素的总个数

max:返回流中元素最大值

min:返回流中元素最小值

List numLists = Arrays.asList(3, 4, 5, 6, 10);

// 全部匹配 - true

boolean allMatch1 = numLists.stream().allMatch(e -> e > 2); //true

System.out.println("allMatch1:" + allMatch1);

// 全部匹配 - true

boolean allMatch2 = numLists.stream().allMatch(e -> e > 5); //false

System.out.println("allMatch2:" + allMatch2);

// 全部都不符合 - true

boolean noneMatch = numLists.stream().noneMatch(e -> e > 20); //true

System.out.println("noneMatch:" + noneMatch);

// 任一元素符合 - true

boolean anyMatch = numLists.stream().anyMatch(e -> e > 4); //true

System.out.println("anyMatch:" + anyMatch);

//返回第一个

Integer findFirst = numLists.stream().findFirst().get(); //3

System.out.println("findFirst:" + findFirst);

//返回任一个

Integer findAny = numLists.stream().findAny().get();

System.out.println("findAny:" + findAny);

//返回 count

long count = numLists.stream().count(); //5

System.out.println("count:" + count);

//返回max

Integer max = numLists.stream().max(Integer::compareTo).get(); //10

System.out.println("max:" + max);

//返回min

Integer min = numLists.stream().min(Integer::compareTo).get();//3

System.out.println("min:" + min);

匹配执行结果

allMatch1:true

allMatch2:false

noneMatch:true

anyMatch:true

findFirst:3

findAny:3

count:5

max:10

min:3

5.组合操作

Reduce 就是组合操作

Reduce(BinaryOperator accumulator) 没有起始值,按照运算规则进行运算操作

解释:第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素,按照函数进行操作;

第二次执行时,第一个参数为第一次函数执行操作的结果,第二个参数为流中的第三个元素;往下依次类推,返回Optinal 通过get()方法获取结果

Reduce(T identity, BinaryOperator accumulator)含有初始值,第二个是第一个的变形,跟第一个方法对比,不同的是此次这个会接受一个identity参数,用来指定Stream循环的初始值。如果Stream为空,就直接返回该值,特殊:该方法不会返回 Optional

Optional sumResult = Stream.of(1, 2, 3, 4)

.reduce((sum, item) -> {

System.out.println("sum : " + sum);

sum += item;

System.out.println("item: " + item);

System.out.println("sum+ : " + sum);

System.out.println("-----——---");

return sum;

});

System.out.println("========sumResult: " + sumResult.get());

Integer sumDefineResult = Stream.of(1, 2, 3, 4)

.reduce(100, (sum, item) -> {

System.out.println("sum : " + sum);

sum += item;

System.out.println("item: " + item);

System.out.println("sum+ : " + sum);

System.out.println("---——-----");

return sum;

});

System.out.println("========sumDefineResult: " + sumDefineResult);

reduce 执行结果

//下面是执行结果

//查看执行结果

sum : 1

item: 2

sum+ : 3

-----——---

sum : 3

item: 3

sum+ : 6

-----——---

sum : 6

item: 4

sum+ : 10

-----——---

========sumResult: 10

sum : 100

item: 1

sum+ : 101

---——-----

sum : 101

item: 2

sum+ : 103

---——-----

sum : 103

item: 3

sum+ : 106

---——-----

sum : 106

item: 4

sum+ : 110

---——-----

========sumDefineResult: 110

6. 收集转换操作

这是个最最最最最基本的操作,10个流操作 9个都会使用到当前操作

collect(Collectors.toList()) 转换List

collect(Collectors.toSet()) 转换Set

Collectors.toMap(key, value) 转换Map ,如果key重复,!!!报错

Collectors.joining() join进行拼接

Collectors.groupingBy(key) 以Key为map的 key分组

Collectors.partitioningBy(规则) 以规则分区 比如 >5 ,map key为true,false

User s1 = new User("aa", 1);

User s2 = new User("bb", 2);

User s3 = new User("cc", 3);

User s4 = new User("dd", 2);

List list = Arrays.asList(s1, s2, s3, s4);

//转换list

List ageList = list.stream().map(User::getAge).collect(Collectors.toList()); // [1, 2, 3]

System.out.println(ageList.toString());

//转成set

Set ageSet = list.stream().map(User::getAge).collect(Collectors.toSet()); // [1, 2, 3]

System.out.println(ageSet);

//转成map,注:key不能相同,否则报错

Map userMap = list.stream().collect(Collectors.toMap(User::getName, User::getAge)); // {cc=10, bb=20, aa=10}

System.out.println(userMap);

//字符串分隔符连接

String joinName = list.stream().map(User::getName).collect(Collectors.joining(",", "(", ")")); // (aa,bb,cc)

System.out.println(joinName);

//分组

Map> ageMap = list.stream().collect(Collectors.groupingBy(User::getAge));

System.out.println(ageMap);

//多重分组,先根据类型分再根据年龄分

Map>> typeAgeMap = list.stream().collect(Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getAge)));

System.out.println(typeAgeMap);

//分区

//分成两部分,true 一部分age大于2岁, false 一部分age小于等于2岁

Map> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 2));

System.out.println(partMap);

collect 执行结果

[1, 2, 3, 2]

[1, 2, 3]

{dd=2, cc=3, bb=2, aa=1}

(aa,bb,cc,dd)

{1=[User{name='aa', age=1}], 2=[User{name='bb', age=2}, User{name='dd', age=2}], 3=[User{name='cc', age=3}]}

{1={1=[User{name='aa', age=1}]}, 2={2=[User{name='bb', age=2}, User{name='dd', age=2}]}, 3={3=[User{name='cc', age=3}]}}

{false=[User{name='aa', age=1}, User{name='bb', age=2}, User{name='dd', age=2}], true=[User{name='cc', age=3}]}

最后

感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值