Java 8 Steam API

92 阅读3分钟

Java 8 Steam API已经问世挺久了,以前也有所运用,觉得使用函数式编程,不能了解背后的原理,因而习惯性的写原生方法,例如写java原生的for来的顺手一些。最近接触了steam API的写法,逐渐重新认识了上它,以后也会在工作中多多用上stream API。

流(Stream)的概念:

流是数据渠道,用于操作数据(集合、数组等)所生成的元素序列。

Stream的操作三个步骤:

  • 创建Stream:一个数据源(如数组、集合),获取一个流
  • 中间操作:一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果

中间操作:

  • filter -------- 接受Lambda ,从流中排除某些元素
  • limit --------- 截断流,使其元素不超过给定数量
  • skip(n) ------- 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
  • distinct ------ 筛选,通过流所生成元素的hashCode() 和 equals() 去除重复元素

映射:

  • map ------ 接收Lambda,将元素转换为其他形式或提取信息(接受一个函数作为参数,该函数被应用到每个元素上,并将其映射成一个新的元素)
  • flatMap ---- 接收一个函数作为参数,将流中的每个值都换成另外一个流,然后把所有的流连凑成一个流。

排序:

  • sorted() ---- 自然排序
  • sorted(Comparator comparator) ------ 定制排序(Comparator )

终止操作

查找与匹配:

  • allMatch ----- 检查是否匹配所有元素
  • anyMatch ------ 检查是否至少匹配一个元素
  • noneMatch --------- 检查是否没有匹配所有元素
  • findFirst ------- 返回第一个元素
  • findAny -------- 返回流中的任意元素
  • count ----------- 返回流中元素的总个数
  • max ------- 返回流中的最大值
  • min ------ 返回流中的最小值

归约:可以将流中元素反复结合起来,得到一个值

  • reduce(T indentity,BinaryOperator bin) ---- indentity 为起始值
  • reduce(BinaryOperator bin)

收集:

  • collect ----- 将流装换为其它形式,接受一个Collector接口的实现,用于给Stream中元素汇总的方法

案例Demo:

#1 新建一个实体类: `

public class Apple {

    private String name;

    private Integer weight;

    private String color;

    private String remark;

    public Apple(String name, Integer weight, String color,String remark) {
        this.name = name;
        this.weight = weight;
        this.color = color;
        this.remark=remark;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

#2 进行初始化List:

List<Apple> appleList = new ArrayList<>();
appleList.add(new Apple("广东",200,"红色","{"Normal":"0","Alarm":"1"}"));
appleList.add(new Apple("华南",200,"绿色","{"Normal":"1","Alarm":"1"}"));
appleList.add(new Apple("湖南",600,"黄色","{"Normal":"1","Alarm":"1"}"));
appleList.add(new Apple("广东",400,"红色","{"Normal":"0","Alarm":"1"}"));
appleList.add(new Apple("广东",50,"蓝色","{"Normal":"0","Alarm":"1"}"));
appleList.add(new Apple("湖南",80,"蓝色","{"Normal":"0","Alarm":"1"}"));

#3 过滤颜色是蓝色的Apple

List<Apple> res2 = appleList.stream().filter(a -> "蓝色".equals(a.getColor())).collect(Collectors.toList());

output:
蓝色-广东
蓝色-湖南

#4 新建一个映射类,AppleMappingEntity,将apple的remark字段的json进行转换,这种情况用stream API就比较方便 高效

public class AppleMappingEntity {


    private ObjectMapper objMapper =  new ObjectMapper();

    private Apple apple;

    private Map<String, String> valueMap;

    public AppleMappingEntity(Apple apple) {
        this.apple=apple;
        valueMap = parseMap(apple.getRemark());
    }

    public Map<String,String> parseMap(String json){
        try{
            Map<String,Object> parseMap = objMapper.readValue(json,Map.class);
            Map<String, String>  resultMap = parseMap.entrySet().stream().collect(
                    Collectors.toMap(e -> e.getKey(), e -> String.valueOf(e.getValue())));
            return resultMap;
        }catch (Exception e){
            e.printStackTrace();
        }
        return new HashMap<>();
    }


    public String getName(){
      return  this.apple.getName();
    }

}

进行调试,查看最终HashMap的结构

Map<String,List<AppleMappingEntity>> convertMap = new HashMap<>();
try{
    convertMap = appleList.stream()
            .map(AppleMappingEntity::new)
            .collect(Collectors.groupingBy(a -> a.getName()));
}catch (Exception ex){
    ex.printStackTrace();
}

System.out.println(convertMap);

image.png

掌握了基础的map映射,编写的代码易读,简洁。借鉴这个场景,在数据量较多的情况,将源数据转成Map,Map在查询时高效,不用再用for去循环查找。