数据统计分析中Treemap 应用实战(排序以及查找离指定key最近的key)
2018-01-30 19:14
701 查看
1. 应用场景
按天统计的逻辑利用hashmap进行存储,另外一篇文章已经提到。现在的问题是查询的交易记录表,如果当天没有交易记录,流量余额就是0,这个是不对的,应该是最近一笔交易记录时的流量余额。
1.必须有序
2.能够查询最近的一个key
此时hashmap不能满足要求,试试treemap,map有序的首选。查询了一下api,竟然支持,我利用的是lowerKey方法
Map.Entry<K,V> | firstEntry() Returns a key-value mapping associated with the least key in this map, or nullif the map is empty. |
K | firstKey() Returns the first (lowest) key currently in this map. |
Map.Entry<K,V> | floorEntry(K key) Returns a key-value mapping associated with the greatest key less than or equal to the given key, or nullif there is no such key. |
K | floorKey(K key) Returns the greatest key less than or equal to the given key, or nullif there is no such key. |
Map.Entry<K,V> | higherEntry(K key) Returns a key-value mapping associated with the least key strictly greater than the given key, or nullif there is no such key. |
K | higherKey(K key) Returns the least key strictly greater than the given key, or nullif there is no such key. |
Set<K> | keySet() Returns a Setview of the keys contained in this map. |
Map.Entry<K,V> | lastEntry() Returns a key-value mapping associated with the greatest key in this map, or nullif the map is empty. |
K | lastKey() Returns the last (highest) key currently in this map. |
Map.Entry<K,V> | lowerEntry(K key) Returns a key-value mapping associated with the greatest key strictly less than the given key, or nullif there is no such key. |
K | lowerKey(K key) Returns the greatest key strictly less than the given key, or nullif there is no such key. |
2. 如何运用
private Map<String, BigDecimal> getRemainingFlux(String channelFlag, Date startTime, Date endTime) {TreeMap<String, BigDecimal> remainingFluxMap = new TreeMap<>((o1, o2) -> o1.compareTo(o2));
AccountInfoExample accountInfoExample = new AccountInfoExample();
accountInfoExample.createCriteria().andDownChannelFlagEqualTo(channelFlag);
List<AccountInfo> accountInfoList = accountInfoMapper.selectByExample(accountInfoExample);
Long accountId = 0L;
if (CollectionUtils.isNotEmpty(accountInfoList)) {
accountId = accountInfoList.get(0).getId();
}
RechargeInfoExample rechargeInfoExample = new RechargeInfoExample();
rechargeInfoExample.createCriteria().andAccountIdEqualTo(accountId);
rechargeInfoExample.setOrderByClause("create_time asc");
List<RechargeInfo> rechargeInfoList = rechargeInfoMapper.selectByExample(rechargeInfoExample);
if (CollectionUtils.isNotEmpty(rechargeInfoList)) {
rechargeInfoList.forEach(rechargeInfo -> {
String date = DateUtils.dateToStr(rechargeInfo.getCreateTime(), 11);
BigDecimal accountBalance = rechargeInfo.getAccountBalance();
remainingFluxMap.put(date, accountBalance);
});
String minDateString = remainingFluxMap.firstKey();
int gapDays = DateUtils.getDaysBetweenDates(endTime, startTime);
for (int i = 0; i <=gapDays; i++) {
Date currentDay = DateUtils.addDay(startTime, i);
String currentDayStr = DateUtils.dateToStr(DateUtils.getDateIgnoreTime(currentDay), 11);
if (remainingFluxMap.get(currentDayStr) == null) {
//无交易记录情况下
Date minDate = null;
try {
minDate = DateUtils.getDateFromStr(minDateString);
} catch (Exception e) {
}
if (DateUtils.getDaysBetweenDates(currentDay, minDate) < 0) {
//小于最早充值记录日期,设置为0
remainingFluxMap.put(DateUtils.dateToStr(DateUtils.getDateIgnoreTime(currentDay), 11), new BigDecimal(0));
} else {
//寻找最近的一笔记录
Map.Entry<String, BigDecimal> availableChargeItemEntry = remainingFluxMap.lowerEntry(currentDayStr);
if (availableChargeItemEntry != null) {
remainingFluxMap.put(currentDayStr, availableChargeItemEntry.getValue());
}
}
}
}
}
return remainingFluxMap;
}1. lowerKey方法寻找的是小于指定key并且最大的一个,要注意很多文章说是上一个key,这个并不准确。指定的key不一定要在map中存在。比如我的指定key就是选择的日期中的某一天,都不在map中存在。
2. 比较器的简洁写法
TreeMap<String, BigDecimal> remainingFluxMap = new TreeMap<>((o1, o2) -> o1.compareTo(o2));
arraylist没有构造方法设置比较器,可以利用下面的写法:
Comparator<ChannelRank> comparator=Comparator.comparing(ChannelRank::getRankScore).reversed();
channelRankList.sort(comparator);
或者
Comparator<VoTransaction> comparator = (h1, h2) -> h2.getTime().compareTo(h1.getTime());
3. 如果声明为Map treeMap=new TreeMap(),则只有map的接口,没有lowerKey这些方法。因为treemap除了实现了map接口,还实现了NavigableMap接口
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{4. 除了比较器,顺便说一下list对filter功能,虽然本case并未运用
List<ChannelDownStreamInfo> channelDownStreamInfoList = channelDownStreamInfoDbList.stream().filter(channelDownStreamInfoDb ->
channelDownStreamInfoDb.getChannelFlag().equalsIgnoreCase(channelDownStreamInfo.getChannelFlag()
) ).collect(Collectors.toList());5. 补充知识点 lamda表达式的作用
只是使用一次的函数,不想去定义名字,也不想去写个复杂的函数结构,这个时候酒用lamda表达式
比如上面list的filter功能,如果不用lamda表达式,filter里面会实现predicted接口,如下:
List<ChannelDownStreamInfo> channelDownStreamInfoList = channelDownStreamInfoDbList.stream().filter(new Predicate<ChannelDownStreamInfo>() {
@Override
public boolean test(ChannelDownStreamInfo channelDownStreamInfoDb) {
return channelDownStreamInfoDb.getChannelFlag().equalsIgnoreCase(channelDownStreamInfo.getChannelFlag());
}
}).collect(Collectors.toList());
channelStateDb = channelDownStreamInfoList.get(0).getChannelState();
}相比之下,lamda表达式简洁很多。
相关文章推荐
- 亿量级流量的数据统计分析以及挖掘技术实战(Spark And Storm)
- 【云星数据---Apache Flink实战系列(精品版)】:Apache Flink高级特性与高级应用006-Slot和Parallelism的深入分析001
- 大数据应用以及原理分析
- 移动应用数据统计分析平台汇总
- 统计分析与数据挖掘所涉及的应用领域探讨
- 算法实战:根据Key或Value对Map进行排序及其应用
- 3款移动应用数据统计分析平台对比
- #数据挖掘与数据化运营实战#2.3数据挖掘技术以及在数据化运营中的应用
- 关于Android大数据收集,埋点统计的详细讲解以及案例代码分析附github代码
- 【二分查找】在排序数组中,找出给定数字的出现次数 以及二分其他应用
- 被遗忘的世界 :二进制 n进制 bit类型在超大数据量统计排序的高效应用
- 统计分析与数据挖掘所涉及的应用领域探讨
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 统计分析与数据挖掘所涉及的应用领域探讨
- 移动应用数据统计分析平台汇总
- 主外键关联数据的处理方式,以及应用场景分析
- 【数据结构与算法】treemap应用 排序
- 【云星数据---Apache Flink实战系列(精品版)】:Apache Flink高级特性与高级应用008-Slot和Parallelism的深入分析003
- Excel在统计分析中的应用—第三章—数据库统计函数与数据透视表-Part1-(数据查询与筛选、分类汇总)
- 实战:mysql统计指定架构的所有表的数据和索引大小情况-v2