业务描述:根据 gameId serverId 两个参数 获取 serverName 。在遍历时需要发送HTTP请求获取。这时想要优化请求次数,便是对List分组。减少发送次数。
这里使用了,Stream 的 分组,这时是使用了两个条件gameId 和 serverId。
final static Cache<String, String> SERVER_NAME_CACHE = CacheBuilder
.newBuilder()
// 设置cache的初始大小为20,要合理设置该值 根据分页数量
.initialCapacity(20)
// 设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作 可以不设置
.concurrencyLevel(5)
// 设置cache中的数据在写入之后的存活时间为10分钟
.expireAfterWrite(10, TimeUnit.MINUTES)
// 构建cache实例
.build();
/**
* 方法说明 : 根据游戏id 服务器id 获取服务请名称时 合并 请求 并缓存
*/
private ConcurrentMap<String, String> mergeRequestWithServerName(
List<WoWorkOrderVo> list) {
ConcurrentMap<String, String> cacheMap = SERVER_NAME_CACHE.asMap();
// 根据 GameId ServerId 分组
Map<Integer, Map<Integer, List<WoWorkOrderVo>>> group = list
.parallelStream()
.collect(Collectors.groupingBy(WoWorkOrderVo::getGameId,
Collectors.groupingBy(WoWorkOrderVo::getServerId)));
// 组织 map k->gameId v->serverId
Map<Integer, Integer> map = new IdentityHashMap<>();
Iterator<Entry<Integer, Map<Integer, List<WoWorkOrderVo>>>> itOut = group
.entrySet().iterator();
// 遍历外层
while (itOut.hasNext()) {
Entry<Integer, Map<Integer, List<WoWorkOrderVo>>> entry = itOut
.next();
Integer keyOut = entry.getKey();
// 获取内层值
Map<Integer, List<WoWorkOrderVo>> value = entry.getValue();
// 遍历内层
Iterator<Entry<Integer, List<WoWorkOrderVo>>> itIn = value
.entrySet().iterator();
while (itIn.hasNext()) {
Entry<Integer, List<WoWorkOrderVo>> next = itIn.next();
Integer keyIn = next.getKey();
map.put(new Integer(keyOut), new Integer(keyIn));
}
}
ConcurrentMap<String, String> gameServerNameMap = new ConcurrentHashMap<>();
map.forEach((k, v) -> {
if (StringUtils.isBlank(cacheMap.get(k + "&" + v))) {
gameServerNameMap.put(k + "&" + v,
agentService.getGameServerName(k, v));
SERVER_NAME_CACHE.put(k + "&" + v,
agentService.getGameServerName(k, v));
}
});
LOGGER.info("【SERVER_NAME_CACHE 缓存MAP的信息{}】", cacheMap.toString());
return cacheMap.isEmpty() ? gameServerNameMap : cacheMap;
}
其实以上方法,是将简单问题复杂化了。线上没有使用这个方法。但是这里的多条件分组,学习了。