设计一个用来返回ECharts数据的视图类

Echarts中图表类型大部分所需要的数据都是一个横坐标对应一至多个纵坐标,有些饼状图类的数据有些特殊,但是绝大部分的图表所需要的数据结构还是一致的,因此这里设计一个视图类用来快速创建像该种图表所需要的数据

思路:由上面的一一对应这种关系,很容易想到使用一个Map结构来保存数据,对于绝大多数的图表结构,其横坐标都是可排序的, 因此我们可以聚合 TreeMap 和 Comparator 这两个对象来完成

public class EChartsVO<X, Y> {
      @JsonValue
      private TreeMap<X, Y> data; // 使用TreeMap存储数据
      private Comparator<? super X> cmp; // 比较器

      /**
       * @param cmp X比较器
       * 传入X的比较器,并初始化TreeMap;
       */
      public EChartsVO(Comparator<? super X> cmp) {
            this.cmp = cmp;
            this.data = new TreeMap<>(cmp);
      }
      /**
       * 默认构造器会将X当作Comparable接口的子类,
       * @throws UnsupportedOperationException 如果横坐标没有实现Comparable将会构造失败抛出 UnsupportedOperationException
       */
      public EChartsVO() {
            this.cmp = new Comparator<X>() {
                  @Override
                  public int compare(X o1, X o2) {
                        if (o1 instanceof Comparable && o2 instanceof Comparable) {
                              return ((Comparable<? super X>) o1).compareTo(o2);
                        } else {
                              throw new UnsupportedOperationException(String.format("Cannot compare instances of type %s", o1.getClass()));
                        }
                  }
            };
            this.data = new TreeMap<>(this.cmp);
      }
      /**
       *   获取的是data的不可变Map
       */
       public Map<X, Y> getData(){return Collections.unmodifiableMap(data);}

      /**
       * 反转data中的数据
       */
      public void reverse() {
            TreeMap<X, Y> map = new TreeMap<>(cmp = this.cmp.reversed());
            map.putAll(this.data);
            this.data = map;
      }

      public void clear(){
            this.data.clear();
      }
}

类的框架和基本构造就写好了, 接下来是提供方法用来保存数据
首先很容易想到保存一组键值对:
 

public void putData(X x, Y y) {
            Objects.requireNonNull(x, "element x can not be null");

            this.data.put(x, y);
}

也可以传入一个现有的Map集合调用Map.putAll()方法快速创建
 

      public void putData(@NotNull Map<? extends X, ? extends Y> arg){
            Set<? extends X> keys = arg.keySet();
            if(keys.stream().anyMatch(Objects::isNull)){
                  throw new IllegalArgumentException("element x can not be null");
            }
            this.data.putAll(arg);
      }

还有一种方式,需要让外界传入数据集合,以及两个Function对象,一个用来将X轴映射出来, 另一个将Y轴映射出来
 

      public <T> void putData(@NotNull Collection<T> list,
                              @NotNull Function<? super T, ? extends X> XMapper,
                              @NotNull Function<? super T ,? extends Y> YMapper){
            Objects.requireNonNull(list);
            Objects.requireNonNull(XMapper);
            Objects.requireNonNull(YMapper);

            Iterator<T> iterator = list.iterator();
            while(iterator.hasNext()){
                  T next = iterator.next();
                  X x;
                  if((x = XMapper.apply(next)) == null){
                        throw new IllegalArgumentException("element x can not be null");
                  }
                  this.data.put(x, YMapper.apply(next));
            }
      }

实际使用:

// 适合 一个X对应一个Y
EChartsVO<String, Integer> vo = new EChartsVO<>();
            if(!CollectionUtils.isEmpty(dtos)){
                  vo.putData(dtos, WorkerRegionCountDTO::getProvince, WorkerRegionCountDTO::getWorkerCount);
            }
//适合一个X对应多个Y
public class InspectAndAttendanceVO {
      public InspectAndAttendanceVO() {
            this.data = new EChartsVO<>();
      }

      private Long workerId;
      private String workerName;
      private String position;
      private EChartsVO<LocalDate, AttendanceVO> data;

      public void addData(String k, List<InspectAndAttendanceDTO> v) {
            String[] baseInfo = k.split("-");
            if (baseInfo.length != 3) {
                  throw new IllegalArgumentException("data is not correct :" + k);
            }
            int idx = 0;
            this.workerId = Long.valueOf(baseInfo[idx++]);
            this.workerName = baseInfo[idx++];
            this.position = baseInfo[idx++];
            Map<LocalDate, AttendanceVO> map = v.stream().collect(Collectors.toMap(InspectAndAttendanceDTO::getDate, AttendanceVO::new));
            this.data.putData(map);
      }

      @Data
      private static class AttendanceVO {
            private Integer isPresent;
            private Integer isInspect;
            public AttendanceVO(InspectAndAttendanceDTO dto) {
                  this.isPresent = dto.getIsPresent();
                  this.isInspect = dto.getIsInspect();
            }
      }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值