JAVA stream()常用方法总结

stream()JAVA8新增的一个强大特性,对于多种集合操作的支持可以极大减少代码量,不多说了,看场景
这有一个Apple的List,需要按照重量进行排序


public class Apple {
    private String name;
    private int weight;
    private String color;
}
//--------------------------------------------------------
 Apple apple1 = new Apple("a1", 80, "red");
 Apple apple2 = new Apple("a2", 30, "green");
 Apple apple3 = new Apple("a3", 30, "blue");
 
 List<Apple> list = Arrays.asList(apple1, apple2, apple3);

这是List自带的方法实现按重量排序:

1:  list.sort((a1,a2) -> a1.getWeight() - a2.getWeight());
2:  list.sort(comparing((Apple a) -> a.getWeight()));
3:  list.sort(comparing(Apple::getWeight));

倒序输出1:  list.sort(comparing(Apple::getWeight).reversed());

是很方便,但是增加条件呢?
接下来,过滤
挑出重量大于150的苹果,别想着foreach了,直接上代码:

List<Aplle> heavyApple = list.stream().filter((Apple a) -> a.getWeight() > 150)
                                              .collect(toList());
List<Aplle> heavyApple = list.parallelStream().filter((Apple a) -> a.getWeight() > 150)
                                              .collect(toList());

其实lamda表达式很好理解,以这段为例:
List heavyApple = list.stream().filter((Apple a) -> a.getWeight() > 150)
.collect(toList());

从头开始看, .filter() 就是动词,正在做过滤操作,过滤条件是什么呢,
(Apple a) -> a.getWeight() > 150 , (Apple a) 是当前比较的实体对象,然后后面跟的是过滤的条件, a.getWeight() > 150,苹果重量大于150(想想是不是很像foreach),最后就是collect(toList()),意为生成一个新的List集合了,每步都透明的表达了自己的用义,阅读起来也很方便.
//-------------------------------------------------------------------------------------------------------

以上两种实现结果是一样的,需要说明一下,streamparallelStream的区别,
parallelStream<<JAVA8实战>>书中解释大意为:…为了更好的利用日益强大的计算机CPU,实现并行处理… 需了解详情请百度.
好了,同理,如果需要找出绿色的苹果:

List<Apple> heavyApple = list.stream().filter(a -> a.getColor().equals("green")).collect(toList());

接着,颜色一样按颜色排序:

list1.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getColor));//没有返回值

前方高能,加量了!!!
需求:菜单选择400卡路里以下食物并排序,把菜肴名称保存在List里面

List<String> lowCaloricDishesName = menu.stream()
         .filter(d -> d.getCalories() < 400)        //小于400的实体
         .sorted(comparing(Dish::getCalories))      //按卡路里(calories)排序
         .map(Dish::getName)                        //只保存名字
         .limit(3)                                  //只选头三个                       
         .collect(toList());

菜肴的实体参数不多,自己脑补啊

获取菜名长度

List<Integer> dishNamelength = menu.stream()
                                   .map(Dish::getName)
                                   .map(String::length)
                                   .collect(toList());

查看是否所有菜品都符合健康(卡路里小于1000)

Boolean  isHealthy = menu.stream()
                         .allMatch(d -> d.getCalories() < 1000);

allMatch,表示是否全部符合,如果条件符合return true,否则 fasle,这个场景也挺多的,数据库查的数据有时做二次过滤可以直接使用,noneMatch和这个作用差不多,标识是否全部不符合

查看是否所有菜品都不符合健康

Boolean  isHealthy = menu.stream()
.noneMatch(d -> d.getCalories()  >=  1000);

数值计算:
求和

List<Integer> stream = Arrays.asList(1, 1, 2, 2);
int sum = nums.stream().reduce(0,Integer :: sum);
//打印: 6

说明一下reduce第一个参数,第一个数我们给出的初始值,用于集合求和之后再对此值进行求和

int sum = nums.stream().reduce(6,Integer :: sum);
//打印: 12

最大值

int sum = nums.stream().reduce(Integer :: max);

最小值

int sum = nums.stream().reduce(Integer :: min);

再说一个筛选去重的方法,distinct

//一个存整数的数组
List<Integer> numList = Arrays.asList(2,5,5,5,6,3,1,7,4);
//获取大于四的所有数(不重复显示)
List<Integer> list5 = numList.stream().filter(a -> a > 4).distinct().collect(Collectors.toList());
//打印结果
System.out.println(list5.toString());
输出:[5, 6, 7]

//获取大于四的所有数(重复显示)
List<Integer> list5 = numList.stream().filter(a -> a > 4).collect(Collectors.toList());
输出:[5, 5, 5, 6, 7]

Map总结

Map<String, String> jsonMap = genJsonList.stream()
.collect(Collectors.toMap(RegexData::getGroupName, RegexData::getValue));

这行是我最近再做Json日志解析时候写的,需求是有两个list,需要对比其中的groupName,如果相等就获取对应的value.写两层List再for一下?虽然list数量不多,效率不会影响太大,但是很麻烦.所以,先把基准list(需要内部遍历的)里每个对象都转成Map<String,String>的键值对,然后只遍历一次外部list,比较的时候直接用基准list生成的map.get(groupName)就行了.当然了,生成Map的Value也可以为实体

Map<Integer, RegexData> regexMap = regexDataList.stream()
.collect(Collectors
.toMap(RegexData::getGroupIndex, RegexData -> RegexData));

只需要在RegexData 实体里加个构造方法就可以了,
注:此方法前提必须是Key为唯一的,Json日志解析出的key没有重复的,如果包含重复key值使用此方法会报错!

如果是使用key,value位为对象List呢,

Apple apple1 = new Apple("a1", 80, "red");
        Apple apple2 = new Apple("a2", 30, "green");
        Apple apple3 = new Apple("a3", 30, "blue");
        Apple apple4 = new Apple("a3", 30, "blue");
Map<String, List<Apple>> map2 = list.stream()
   .collect(Collectors.groupingByConcurrent(Apple::getColor));

打印结果:

{red=[NomarlizeTest.Lamda.Apple@2aae9190], 
green=[NomarlizeTest.Lamda.Apple@2f333739], 
blue=[NomarlizeTest.Lamda.Apple@77468bd9, NomarlizeTest.Lamda.Apple@12bb4df8]}

使用groupingByConcurrent,解析结果red和green都只有一个对象,blue有两个对象

//从list集合中,取出字段name的列表
List names = list.stream().map(p -> p.getName()).collect(Collectors.toList());

这里记录一些比较常用的,stream还有很多的处理方法,可以大大节省代码量

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值