流创建
方法 | |
---|---|
集合 | collection.stream/parllelstream |
数组 | arrays.stream |
数字stream | intstream/longstream.range/rangeclosed/random.inis/longs/doubles |
自己创建 | stream.generate/iterate |
1、list 转 map
工作中,我们经常遇到list
转map
的案例。collectors.tomap
就可以把一个list
数组转成一个map
。代码如下:
public class testlambda { public static void main(string[] args) { list<userinfo> userinfolist = new arraylist<>(); userinfolist.add(new userinfo(1l, "测试源码", 18)); userinfolist.add(new userinfo(2l, "程序员淘淘", 27)); userinfolist.add(new userinfo(2l, "打代码的淘淘", 26)); /** * list 转 map * 使用collectors.tomap的时候,如果有可以重复会报错,所以需要加(k1, k2) -> k1 * (k1, k2) -> k1 表示,如果有重复的key,则保留第一个,舍弃第二个 */ map<long, userinfo> userinfomap = userinfolist.stream().collect(collectors.tomap(userinfo::getuserid, userinfo -> userinfo, (k1, k2) -> k1)); userinfomap.values().foreach(a->system.out.println(a.getusername())); } }
类似的,还有collectors.tolist()
、collectors.toset()
,表示把对应的流转化为list
或者set
。
2、filter()过滤
从数组集合中,过滤掉不符合条件的元素,留下符合条件的元素。
list<userinfo> userinfolist = new arraylist<>(); userinfolist.add(new userinfo(1l, "测试源码", 18)); userinfolist.add(new userinfo(2l, "程序员淘淘", 27)); userinfolist.add(new userinfo(3l, "打代码的淘淘", 26)); /** * filter 过滤,留下超过18岁的用户 */ list<userinfo> userinforesultlist = userinfolist.stream().filter(user -> user.getage() > 18).collect(collectors.tolist()); userinforesultlist.foreach(a -> system.out.println(a.getusername())); //运行结果 程序员淘淘 打代码的淘淘
3、foreach遍历
foreach
遍历list,遍历map,真的很丝滑。
/** * foreach 遍历集合list列表 */ list<string> usernamelist = arrays.aslist("测试源码", "程序员淘淘", "艿艿"); usernamelist.foreach(system.out::println); hashmap<string, string> hashmap = new hashmap<>(); hashmap.put("号码你", "测试源码"); hashmap.put("职业", "程序员淘淘"); hashmap.put("昵称", "艿艿"); /** * foreach 遍历集合map */ hashmap.foreach((k, v) -> system.out.println(k + ":\t" + v)); //运行结果 测试源码 程序员淘淘 打代码的淘淘 职业: 程序员淘淘 号码你: 测试源码 昵称: 艿艿
4、groupingby 分组
提到分组,相信大家都会想起sql
的group by
。我们经常需要一个list做分组操作。比如,按城市分组用户。在java8之前,是这么实现的:
list<userinfo> originuserinfolist = new arraylist<>(); originuserinfolist.add(new userinfo(1l, "测试源码", 18,"深圳")); originuserinfolist.add(new userinfo(3l, "打代码的淘淘", 26,"湛江")); originuserinfolist.add(new userinfo(2l, "程序员淘淘", 27,"深圳")); map<string, list<userinfo>> result = new hashmap<>(); for (userinfo userinfo : originuserinfolist) { string city = userinfo.getcity(); list<userinfo> userinfos = result.get(city); if (userinfos == null) { userinfos = new arraylist<>(); result.put(city, userinfos); } userinfos.add(userinfo); }
而使用java8
的groupingby
分组器,清爽无比:
map<string, list<userinfo>> result = originuserinfolist.stream() .collect(collectors.groupingby(userinfo::getcity));
5、sorted+comparator 排序
工作中,排序的需求比较多,使用sorted+comparator
排序,真的很香。
list<userinfo> userinfolist = new arraylist<>(); userinfolist.add(new userinfo(1l, "测试源码", 18)); userinfolist.add(new userinfo(3l, "打代码的淘淘", 26)); userinfolist.add(new userinfo(2l, "程序员淘淘", 27)); /** * sorted + comparator.comparing 排序列表, */ userinfolist = userinfolist.stream().sorted(comparator.comparing(userinfo::getage)).collect(collectors.tolist()); userinfolist.foreach(a -> system.out.println(a.tostring())); system.out.println("开始降序排序"); /** * 如果想降序排序,则可以使用加reversed() */ userinfolist = userinfolist.stream().sorted(comparator.comparing(userinfo::getage).reversed()).collect(collectors.tolist()); userinfolist.foreach(a -> system.out.println(a.tostring())); //运行结果 userinfo{userid=1, username='测试源码', age=18} userinfo{userid=3, username='打代码的淘淘', age=26} userinfo{userid=2, username='程序员淘淘', age=27} 开始降序排序 userinfo{userid=2, username='程序员淘淘', age=27} userinfo{userid=3, username='打代码的淘淘', age=26} userinfo{userid=1, username='测试源码', age=18} -=----------------------------------------------------------------- private static void test04(){ // 按工资升序排序(自然排序) list<string> newlist = personlist.stream().sorted(comparator.comparing(person::getsalary)).map(person::getname) .collect(collectors.tolist()); // 按工资倒序排序 list<string> newlist2 = personlist.stream().sorted(comparator.comparing(person::getsalary).reversed()) .map(person::getname).collect(collectors.tolist()); // 先按工资再按年龄升序排序 list<string> newlist3 = personlist.stream() .sorted(comparator.comparing(person::getsalary).thencomparing(person::getage)).map(person::getname) .collect(collectors.tolist()); // 先按工资再按年龄自定义排序(降序) list<string> newlist4 = personlist.stream().sorted((p1, p2) -> { if (p1.getsalary() == p2.getsalary()) { return p2.getage() - p1.getage(); } else { return p2.getsalary() - p1.getsalary(); } }).map(person::getname).collect(collectors.tolist()); system.out.println("按工资升序排序:" + newlist); system.out.println("按工资降序排序:" + newlist2); system.out.println("先按工资再按年龄升序排序:" + newlist3); system.out.println("先按工资再按年龄自定义降序排序:" + newlist4); }
6、distinct去重
distinct
可以去除重复的元素:
list<string> list = arrays.aslist("a", "b", "f", "a", "c"); list<string> temp = list.stream().distinct().collect(collectors.tolist()); temp.foreach(system.out::println);
7、findfirst返回第一个
findfirst
很多业务场景,我们只需要返回集合的第一个元素即可:
list<string> list = arrays.aslist("a", "b", "f", "a", "c"); list.stream().findfirst().ifpresent(system.out::println);
8、anymatch 是否至少匹配一个元素
anymatch
检查流是否包含至少一个满足给定谓词的元素。
stream<string> stream = stream.of("a", "b", "c", "d"); boolean match = stream.anymatch(s -> s.contains("c")); system.out.println(match); //输出 true
9、allmatch 匹配所有元素
allmatch
检查流是否所有都满足给定谓词的元素。
stream<string> stream = stream.of("a", "b", "c", "d"); boolean match = stream.allmatch(s -> s.contains("c")); system.out.println(match); //输出 false
10、map 转换
map
方法可以帮我们做元素转换,比如一个元素所有字母转化为大写,又或者把获取一个元素对象的某个属性,demo
如下:
list<string> list = arrays.aslist("jay", "tianluo"); //转化为大写 list<string> uppercaselist = list.stream().map(string::touppercase).collect(collectors.tolist()); uppercaselist.foreach(system.out::println);
11、reduce
reduce可以合并流的元素,并生成一个值
int sum = stream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b); system.out.println(sum); /** * 求integer集合的元素之和、乘积和最大值 * */ private static void test13() { list<integer> list = arrays.aslist(1, 2, 3, 4); //求和 optional<integer> reduce = list.stream().reduce((x,y) -> x+ y); system.out.println("求和:"+reduce); //求积 optional<integer> reduce2 = list.stream().reduce((x,y) -> x * y); system.out.println("求积:"+reduce2); //求最大值 optional<integer> reduce3 = list.stream().reduce((x,y) -> x>y?x:y); system.out.println("求最大值:"+reduce3); } /* * 求所有员工的工资之和和最高工资 */ private static void test14() { initperson(); optional<integer> reduce = personlist.stream().map(person :: getsalary).reduce(integer::sum); optional<integer> reduce2 = personlist.stream().map(person :: getsalary).reduce(integer::max); system.out.println("工资之和:"+reduce); system.out.println("最高工资:"+reduce2); }
12、peek 打印个日志
peek()
方法是一个中间stream
操作,有时候我们可以使用peek
来打印日志。
list<string> result = stream.of("程序员淘淘", "测试源码", "打代码的淘淘") .filter(a -> a.contains("芋艿")) .peek(a -> system.out.println("关注号码你:" + a)).collect(collectors.tolist()); system.out.println(result); //运行结果 关注号码你:程序员淘淘 关注号码你:测试源码 [程序员淘淘, 测试源码]
13、max,min 最大最小
使用lambda流求最大,最小值,非常方便。
list<userinfo> userinfolist = new arraylist<>(); userinfolist.add(new userinfo(1l, "测试源码", 18)); userinfolist.add(new userinfo(3l, "打代码的淘淘", 26)); userinfolist.add(new userinfo(2l, "程序员淘淘", 27)); optional<userinfo> maxageuserinfoopt = userinfolist.stream().max(comparator.comparing(userinfo::getage)); maxageuserinfoopt.ifpresent(userinfo -> system.out.println("max age user:" + userinfo)); optional<userinfo> minageuserinfoopt = userinfolist.stream().min(comparator.comparing(userinfo::getage)); minageuserinfoopt.ifpresent(userinfo -> system.out.println("min age user:" + userinfo)); //运行结果 max age user:userinfo{userid=2, username='程序员淘淘', age=27} min age user:userinfo{userid=1, username='测试源码', age=18}
14、count 统计
一般count()
表示获取流数据元素总数。
list<userinfo> userinfolist = new arraylist<>(); userinfolist.add(new userinfo(1l, "测试源码", 18)); userinfolist.add(new userinfo(3l, "打代码的淘淘", 26)); userinfolist.add(new userinfo(2l, "程序员淘淘", 27)); long count = userinfolist.stream().filter(user -> user.getage() > 18).count(); system.out.println("大于18岁的用户:" + count); //输出 大于18岁的用户:2 /** * 统计员工人数、平均工资、工资总额、最高工资 */ private static void test01(){ //统计员工人数 long count = personlist.stream().collect(collectors.counting()); //求平均工资 double average = personlist.stream().collect(collectors.averagingdouble(person::getsalary)); //求最高工资 optional<integer> max = personlist.stream().map(person::getsalary).collect(collectors.maxby(integer::compare)); //求工资之和 integer sum = personlist.stream().collect(collectors.summingint(person::getsalary)); //一次性统计所有信息 doublesummarystatistics collect = personlist.stream().collect(collectors.summarizingdouble(person::getsalary)); system.out.println("统计员工人数:"+count); system.out.println("求平均工资:"+average); system.out.println("求最高工资:"+max); system.out.println("求工资之和:"+sum); system.out.println("一次性统计所有信息:"+collect); }
15、提取/组合
流也可以进行合并、去重、限制、跳过等操作。
private static void test05(){ string[] arr1 = { "a", "b", "c", "d" }; string[] arr2 = { "d", "e", "f", "g" }; stream<string> stream1 = stream.of(arr1); stream<string> stream2 = stream.of(arr2); // concat:合并两个流 distinct:去重 list<string> newlist = stream.concat(stream1, stream2).distinct().collect(collectors.tolist()); // limit:限制从流中获得前n个数据 list<integer> collect = stream.iterate(1, x -> x + 2).limit(10).collect(collectors.tolist()); // skip:跳过前n个数据 list<integer> collect2 = stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(collectors.tolist()); system.out.println("流合并:" + newlist); system.out.println("limit:" + collect); system.out.println("skip:" + collect2); }
16、连接joining
joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
list<integer> list = arrays.aslist(7, 6, 9, 3, 10, 2, 1); string collect = list.stream().map(string::valueof).collect(collectors.joining(",")); system.out.println(collect); 7,6,9,3,10,2,1
17、常用函数式接口
其实lambda离不开函数式接口,我们来看下jdk8常用的几个函数式接口:
function<t, r>
(转换型): 接受一个输入参数,返回一个结果consumer<t>
(消费型): 接收一个输入参数,并且无返回操作predicate<t>
(判断型): 接收一个输入参数,并且返回布尔值结果supplier<t>
(供给型): 无参数,返回结果
function<t, r>
是一个功能转换型的接口,可以把将一种类型的数据转化为另外一种类型的数据
private void testfunction() { //获取每个字符串的长度,并且返回 function<string, integer> function = string::length; stream<string> stream = stream.of("程序员淘淘", "测试源码", "打代码的淘淘"); stream<integer> resultstream = stream.map(function); resultstream.foreach(system.out::println); }
consumer<t>
是一个消费性接口,通过传入参数,并且无返回的操作
private void testcomsumer() { //获取每个字符串的长度,并且返回 consumer<string> comsumer = system.out::println; stream<string> stream = stream.of("程序员淘淘", "测试源码", "打代码的淘淘"); stream.foreach(comsumer); }
predicate<t>
是一个判断型接口,并且返回布尔值结果.
private void testpredicate() { //获取每个字符串的长度,并且返回 predicate<integer> predicate = a -> a > 18; userinfo userinfo = new userinfo(2l, "程序员淘淘", 27); system.out.println(predicate.test(userinfo.getage())); }
supplier<t>
是一个供给型接口,无参数,有返回结果。
private void testsupplier() { supplier<integer> supplier = () -> integer.valueof("666"); system.out.println(supplier.get()); }
这几个函数在日常开发中,也是可以灵活应用的,比如我们dao操作完数据库,是会有个result的整型结果返回。我们就可以用supplier<t>
来统一判断是否操作成功。如下:
private void savedb(supplier<integer> supplier) { if (supplier.get() > 0) { system.out.println("插入数据库成功"); }else{ system.out.println("插入数据库失败"); } } @test public void add() throws exception { course course=new course(); course.setcname("java"); course.setuserid(100l); course.setcstatus("normal"); savedb(() -> coursemapper.insert(course)); }
到此这篇关于java stream操作转换方法的文章就介绍到这了,更多相关java stream操作内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论