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
null if 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
null if there is no such key.
|
K |
floorKey(K key)
Returns the greatest key less than or equal to the given key, or
null if 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
null if there is no such key.
|
K |
higherKey(K key)
Returns the least key strictly greater than the given key, or
null if there is no such key.
|
Set<K> |
keySet()
Returns a
Set view 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
null if 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
null if there is no such key.
|
K |
lowerKey(K key)
Returns the greatest key strictly less than the given key, or
null if 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表达式简洁很多。