GFStableList Adapter
STL中,list的优点是插入、删除性能极佳(时间复杂度只需O(1)即可),而且非常重要的在删除节点后,其迭代器不失效,但list查找却不擅长。map由于其实现的数据结构为rb-tree,因此,其插入、删除以及查找的性能也都是非常不错的。如:插入、删除操作在多数情况下,可能只需要几个简单的数据交换、节点旋转即可达到目的,在这样情况下,时间复杂度也只有O(1)即可(当然,在最糟糕情况下,如插入、删除的时候产生上溯时,则时间复杂度最坏情况有可能达到2logN = O(logN),但由于rb-tree的性质原因,会产生最坏情况的机会也会比较少,而且大量试验证明,rb-tree的平均性能都是非常好的)。但是map容器在删除节点时,其迭代器是失效的。
但在项目开发(尤其是在游戏项目开发)中,像设计角色管理器、技能管理器、buff管理器等等时候,经常会遇到这样一个问题(说明:此处以角色管理器为例说明)如下:
问题
游戏中(或战场中吧),每一个角色对象都有一个唯一Id,那么,这些游戏中的对象该如何维护?
解决
见过有的项目中是将这些角色对象用map来维护的。看上去好像是比较理想,因为它查找非常方便,而且在实际当中,也的的确确是需要频繁根据唯一Id查找对应的角色对象。但用map有个问题,在这些对象更新时,有可能会遇到角色死亡的情况,此时该如何处理这个对象?是立即移除?是先打标记然后再在全部更新之后,再一次性全部移除?又或者是都不移除只是不再更新它而已?事实上,这些处理方案都不理想。事实上,用这个方案的项目,最终的结果是:因为没办法在更新时移时移除掉这些“垃圾”角色对象,性能好坏且不说,整个代码最后都显得比较乱。因为用户在到处查找使用时,都是小心查看取出来的该对象是否是有效的。
另一种维护方案是使用list。该方案不必多说,数据组织与更新、移除都没啥大问题,就是查找效率不高。
鉴于前面综述情况,特地设计一个容器适配器GFStableList,其功能类似list,但却具有map的查找性能,并且支持erase时,reverse_iterator参数。编码如下:
#pragma once #include "src/Common/IncludeHeaders.h" /******************************************************************************
* create : (jacc.kim) [3-1-2016]
* summary : class GFStableList.
* !!!note : 01.该列表中的元素的"Id"是不可以重复的.
* 02.该列表稳定、支持快速查找、类似std::list删除时迭代器有效.
* 03.使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
* 使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
* 使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
******************************************************************************/
template<typename TValue, typename TId>
class GFStableList
{
public:
typedef typename std::list<TValue> value_list;
typedef typename value_list::value_type value_type;
typedef typename value_list::pointer pointer;
typedef typename value_list::const_pointer const_pointer;
typedef typename value_list::reference reference;
typedef typename value_list::const_reference const_reference;
typedef typename value_list::difference_type difference_type;
typedef typename value_list::size_type size_type;
typedef typename value_list::iterator iterator;
typedef typename value_list::const_iterator const_iterator;
typedef typename value_list::reverse_iterator reverse_iterator;
typedef typename value_list::const_reverse_iterator const_reverse_iterator; typedef typename TId id_type;
typedef typename std::function<id_type(const_reference)> TGFvalueIdGetter;
typedef typename std::function<void(const_reference)> TGFvalueDeleter; public:
GFStableList();
explicit GFStableList(const TGFvalueIdGetter& getter);
GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter);
~GFStableList(); void setValueIdGetter(const TGFvalueIdGetter& getter);
void setValueDeleter(const TGFvalueDeleter& deleter); // !!!note: only no exist items & valid items will be insert or push.
const bool push_front(const_reference value);
const bool push_back(const_reference value);
iterator insert(const_iterator _where, const_reference value);
iterator insert(const_iterator _where, const_iterator _first, const_iterator _last); iterator erase(const_reference value);
iterator erase(const id_type& id);
iterator erase(const_iterator _first, const_iterator _last);
iterator erase(const_iterator _where);
reverse_iterator erase(reverse_iterator _first, reverse_iterator _last);
reverse_iterator erase(reverse_iterator _where);
const_reverse_iterator erase(const_reverse_iterator _first, const_reverse_iterator _last);
const_reverse_iterator erase(const_reverse_iterator _where);
void clear();
iterator find(const id_type& id);
const_iterator find(const id_type& id) const; iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const; reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const; const_iterator cbegin() const;
const_iterator cend() const;
const_reverse_iterator crbegin() const;
const_reverse_iterator crend() const; reference front();
reference back();
const_reference front() const;
const_reference back() const; void pop_front();
void pop_back(); bool empty();
size_type size(); private:
GFStableList(const GFStableList<TValue, TId>& listValues) = delete; private:
typedef typename std::map<id_type, iterator> id_value_map; void _clearValueList();
void _clearMapping();
iterator _locate(const_reference value);
const_iterator _locate(const_reference value) const;
iterator _locate(const id_type& id);
const_iterator _locate(const id_type& id) const;
const bool _isExisted(const id_type& id);
const bool _isExisted(const_reference value);
const id_type _getValueId(const_reference value); private:
TGFvalueIdGetter m_IdGetter;
TGFvalueDeleter m_ValueDeleter;
value_list m_listValues;
id_value_map m_mapMapping; };//template<typename TValue, typename TId> class GFStableList #include "src/Common/GFStableList.inl"
GFStableList.h文件
#include "src/Common/IncludeHeaders.h" ///////////////////////////////////////////////////////////////////////////////
// template<typename TValue, typename TId> class GFStableList
template<typename TValue, typename TId>
GFStableList<TValue, TId>::GFStableList() : m_IdGetter (nullptr)
, m_ValueDeleter(nullptr)
, m_listValues ()
, m_mapMapping ()
{ } template<typename TValue, typename TId>
GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter) : m_IdGetter (getter)
, m_ValueDeleter(nullptr)
, m_listValues ()
, m_mapMapping ()
{ } template<typename TValue, typename TId>
GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter) : m_IdGetter (getter)
, m_ValueDeleter(deleter)
, m_listValues ()
, m_mapMapping ()
{ } template<typename TValue, typename TId>
GFStableList<TValue, TId>::~GFStableList() {
this->clear();
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::setValueIdGetter(const TGFvalueIdGetter& getter) {
m_IdGetter = getter;
//GFAssert(nullptr != m_IdGetter, "the id getter is nullptr.");
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::setValueDeleter(const TGFvalueDeleter& deleter) {
m_ValueDeleter = deleter;
} template<typename TValue, typename TId>
const bool GFStableList<TValue, TId>::push_front(const_reference value) {
return insert(begin(), value) != end();
} template<typename TValue, typename TId>
const bool GFStableList<TValue, TId>::push_back(const_reference value) {
return insert(end(), value) != end();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_reference value) {
if (nullptr == value) {
return end();
} const auto id = _getValueId(value);
if (_isExisted(id)) {
return end();// 已经存在了.
} auto iter = m_listValues.insert(_where, value);
m_mapMapping[id] = iter;
return iter;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_iterator _first, const_iterator _last) {
if (_first == end() || _first == _last) {
return;
}
auto insert_pos = end();
iterator tmpResult;
id_type id;
for (auto iter = _first; iter != _last; ++iter) {
id = _getValueId(*iter);
if (_isExisted(id)) {
continue;// id is existed.
}
tmpResult = m_listValues.insert(_where, *iter);
m_mapMapping[id] = tmpResult; if (insert_pos == end()) {
insert_pos = tmpResult;
}
}
return insert_pos;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_reference value) {
auto iter = _locate(value);
return erase(iter);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const id_type& id) {
auto iter = _locate(id);
return erase(iter);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _first, const_iterator _last) {
if (_first == end()) {
return end();
}
if (_first == begin() && _last == end()) {
this->clear();
return end();
}
iterator retIter = end();
auto iter = _first;
while (iter != _last && iter != end()) {
retIter = this->erase(iter);
iter = retIter;
}
return retIter;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _where) {
if (_where == end()) {
return end();
}
const auto id = _getValueId(*_where);
m_mapMapping.erase(id);
return m_listValues.erase(_where);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _first, reverse_iterator _last) {
if (_first == rend()) {
return rend();
}
if (_first == rbegin() && _last == rend()) {
this->clear();
return rend();
}
reverse_iterator retIter = rend();
auto iter = _first;
while (iter != _last && iter != rend()) {
retIter = this->erase(iter);
iter = retIter;
}
return retIter;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _where) {
if (_where == rend()) {
return rend();
} auto ret_iter = _where; // 返回值.
++ret_iter; const auto id = _getValueId(*_where.base());
this->erase(id); return ret_iter;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _first, const_reverse_iterator _last) {
if (_first == rend()) {
return rend();
}
if (_first == rbegin() && _last == rend()) {
this->clear();
return rend();
}
const_reverse_iterator retIter = rend();
auto iter = _first;
while (iter != _last && iter != rend()) {
retIter = this->erase(iter);
iter = retIter;
}
return retIter;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _where) {
if (_where == rend()) {
return rend();
} auto ret_iter = _where; // 返回值.
++ret_iter; const auto id = _getValueId(*_where.base());
this->erase(id); return ret_iter;
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::clear() {
_clearValueList();
_clearMapping();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::find(const id_type& id) {
return _locate(id);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::find(const id_type& id) const {
return _locate(id);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::begin() {
return m_listValues.begin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::begin() const {
return m_listValues.begin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::end() {
return m_listValues.end();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::end() const {
return m_listValues.end();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rbegin() {
return m_listValues.rbegin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rbegin() const {
return m_listValues.rbegin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rend() {
return m_listValues.rend();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rend() const {
return m_listValues.rend();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cbegin() const {
return m_listValues.cbegin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cend() const {
return m_listValues.cend();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crbegin() const {
return m_listValues.crbegin();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crend() const {
return m_listValues.crend();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::front() {
return m_listValues.front();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::back() {
return m_listValues.back();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::front() const {
return m_listValues.front();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::back() const {
return m_listValues.end();
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::pop_front() {
if (this->empty()) {
return;
}
auto iter = this->begin();
const auto id = _getValueId(*iter);
this->erase(id);
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::pop_back() {
if (this->empty()) {
return;
}
auto riter = this->rbegin();
const auto id = _getValueId(*riter);
this->erase(id);
} template<typename TValue, typename TId>
bool GFStableList<TValue, TId>::empty() {
return m_listValues.empty();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::size_type GFStableList<TValue, TId>::size() {
return m_listValues.size();
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::_clearValueList() {
if (nullptr != m_ValueDeleter) {
auto iter = m_listValues.begin();
auto iterend = m_listValues.end();
for (; iter != iterend; ++iter) {
m_ValueDeleter(*iter);
}
}
m_listValues.clear();
} template<typename TValue, typename TId>
void GFStableList<TValue, TId>::_clearMapping() {
m_mapMapping.clear();
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const_reference value) {
const auto id = m_IdGetter(value);
return _locate(id);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const_reference value) const {
const auto id = m_IdGetter(value);
return _locate(id);
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const id_type& id) {
auto iter = m_mapMapping.find(id);
if (iter == m_mapMapping.end()) {
return end();
}
return iter->second;
} template<typename TValue, typename TId>
typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const id_type& id) const {
auto iter = m_mapMapping.find(id);
if (iter == m_mapMapping.end()) {
return end();
}
return iter->second;
} template<typename TValue, typename TId>
const bool GFStableList<TValue, TId>::_isExisted(const id_type& id) {
auto iter = m_mapMapping.find(id);
return iter != m_mapMapping.end();
} template<typename TValue, typename TId>
const bool GFStableList<TValue, TId>::_isExisted(const_reference value) {
auto id = _getValueId(value);
return _isExisted(id);
} template<typename TValue, typename TId>
typename const GFStableList<TValue, TId>::id_type GFStableList<TValue, TId>::_getValueId(const_reference value) {
return m_IdGetter(value);
}
GFStableList.inl文件
GFStableList Adapter的更多相关文章
- 设计模式(七): 通过转接头来观察"适配器模式"(Adapter Pattern)
在前面一篇博客中介绍了“命令模式”(Command Pattern),今天博客的主题是“适配器模式”(Adapter Pattern).适配器模式用处还是比较多的,如果你对“适配器模式”理解呢,那么自 ...
- 设计模式(七)适配器模式(Adapter Pattern)
一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...
- ListView和Adapter数据适配器的简单介绍
ListView 显示大量相同格式数据 常用属性: listSelector listView每项在选中.按下等不同状态时的Drawable divider ...
- Android之RecyclerView的原生Bug-Inconsistency detected. Invalid view holder adapter positionViewHolder{a1bbfa3 position=2 id=-1, oldPos=-1, pLpos:-1 no parent}
今天在运行自己编写的App时,突然发现App在运行时闪退,然后就查看了Android Studio的Log,发现了这个错误,上网查了一下,才知道是RecyclerView的原生Bug,在数据更新时会出 ...
- Android——Adapter
Adapter——本身只是一个接口.Adapter是将数据绑定到UI界面上的桥接类.Adapter负责创建显示每个项目的子View和提供对下层数据的访问. 数据适配器作用:把复杂的数据(数组.链表.数 ...
- 设计模式--适配器模式Adapter(结构型)
一.适配器模式 适配器模式的主要作用是在新接口和老接口之间进行适配.将一个类的接口转换成客户端期望的另外一个接口.其实适配器模式有点无赖之举,在前期设计的时候,我们就不应该考虑适配器模式,而应该通过重 ...
- Android 利用RecyclerView.Adapter刷新列表中的单个view问题
首先使用RecyclerView的adapter继承:RecyclerView.Adapter public class OrderListAdapter extends RecyclerView.A ...
- oracle plsql 无法连接 报 ORA-12560: TNS:protocol adapter error
ORA-12560: TNS:protocol adapter error 添加一个环境变量,名为TNS_ADMIN,值为 tnsnames.ora 文件所在路径.比如我的本机为:D:/instant ...
- C#设计模式系列:适配器模式(Adapter)
在实际的软件系统设计和开发中,为了完成某项工作需要购买一个第三方的库来加快开发.这带来一个问题,在应用程序中已经设计好的功能接口,与这个第三方提供的接口不一致.为了使得这些接口不兼容的类可以在一起工作 ...
随机推荐
- Merge into(oracle)
作用:使用一条sql语句进行insert或者update操作,如果存在就update,如果不存在就insert 语法: MERGE INTO table_name t1 USING (table|vi ...
- Python根据上下限生成不重复随机数
Python 2.7.5 代码: # coding=gbk import random import sys min_num = input('输入下限:') max_num = input('输入上 ...
- 我的学习笔记之node----node.js+socket.io实时聊天(1) (谨此纪念博客开篇)
本想着从hello word开篇,也确实写了相关学习笔记.各种原因吧,现在又着急写出作品,便作罢. 这里将记录一个node.js+socket.io的实时聊天程序.(当然我也是跟着网上各种教程资料学习 ...
- Marzoni(玛佐尼)意大利顶级西服面料之一_HollandandSherry_新浪博客
Marzoni(玛佐尼)意大利顶级西服面料之一_HollandandSherry_新浪博客 Marzoni(玛佐尼)意大利顶级西服面料之一 (2013-01-08 17:30:04) 转载▼
- poj3258
题目翻译 二分法(其实两个单词的意思分别是河,跳格子游戏,至于为啥翻译成二分法- -只能说英语博大精深啊) 奶牛每年举办一场有特色的跳格子游戏(很明显题目翻译错误)涉及到在河里从一块岩石跳到另一块岩石 ...
- OC类方法和实例方法 及常用的for/in方法
类方法前面有+,实例方法前面有- 类方法和实例方法的区别在于,类方法不能使用实例变量. 使用类方法主要原因有: 1.类方法的使用不依赖于实例化一个对象,也就是说如果一个功能的实现不需要实例化对象,就可 ...
- 最常用的Eclipse快捷键【转载】
本文是一些最实用.最齐全.最省时间的 Eclipse 快捷键总结,这些快捷键可以让帮助你完成工作中的任何一个操作.欢迎参考. 1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间 ...
- 关于node升级到7.0,无法gulp alljs的问题
http://stackoverflow.com/questions/40308623/cannot-find-module-internal-fs-afer-upgrading-to-node-7 ...
- 【动态页面】(二)Java反射
Java的反射机制是Java语言非常重要的一个特性.先从Sun官网上看一下官网是怎样定义反射机制的. 大致翻译一下,翻译的可能不是非常准确. 反射(Reflection)是Java程序设计语言的一个特 ...
- Gradle 1.12 翻译——第十三章 编写构建脚本
有关其它已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或訪问:http://gradledoc.qiniudn.com ...