UE常用容器之TMap

TMap 是虚幻C++中的散列容器,主要由一个键类型和一个值类型,以关联对TPair的形式存储在映射中。键类型必须支持 GetTypeHash 函数,并提供运算符 == 来比较各个键是否等值。TMap 也可使用任选分配器来控制内存分配行为。

示例代码如下:

//=========================================================================================//初始化
TMap FoodMap;  //空



//=========================================================================================
//使用结构体当作Key
// 声明结构体,定义操作符 == 和函数 GetTypeHash。
USTRUCT(BlueprintType)
struct FMyStruct
{
	GENERATED_USTRUCT_BODY()

	EMyEnum EnumA;
	EMyEnum EnumB;

	friend inline bool operator==(const FMyStruct& A, const FMyStruct& B)
	{
		return A.EnumA == B.EnumA && A.EnumB == B.EnumB;
	}

	friend inline uint32 GetTypeHash(const FMyStruct& C)
	{
		uint32 Hash = 0;

		Hash = HashCombine(Hash, GetTypeHash(C.EnumA));
		Hash = HashCombine(Hash, GetTypeHash(C.EnumB));
		return Hash;
	}
};
// 使用 FMyStruct 当 Key。但是不支持蓝图了。
TMap MyMap;



//========================================================================================
//增
TMap FoodMapA;

// 使用 Add 或 Emplace 添加元素
// 与 TArray 类似,Emplace 可以避免创建不必要的临时变量,效率比 Add 高。
// 各个键都必定是唯一。
// 如果尝试添加重复键,将替换原来的键值。
FoodMapA.Add(3, TEXT("Banana"));
FoodMapA.Add(6, TEXT("Apple"));
/** 当前TMap为:
 * FoodMapA == [
 *  { Key:3, Value:"Banana"},
 *  { Key:6, Value:"Apple" }]
*/
FoodMapA.Add(3, TEXT("Orange"));
FoodMapA.Emplace(7, TEXT("Cake"));
/** 当前TMap为:
 * FoodMapA == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/

// 使用 Append 函数合并映射,将一个映射的所有元素移至另一个映射。
// Apeend的Map映射的相同键会替代原映射中的键。
/** 存在一个TMap为:
 * FoodMapB == [
 *  { Key:3, Value:"Sweet"},
 *  { Key:1, Value:"Water" }
 *  { Key:9, Value:"Cola" }]
*/

FoodMapA.Append(FoodMapB);
/** 当前TMap为:
 * FoodMapA == [
 *  { Key:3, Value:"Sweet"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" },
 *  { Key:1, Value:"Water" },
 *  { Key:9, Value:"Cola" }]
*/


//======================================================================================
//删
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/

// 使用 Remove 函数移除元素。
// 移除元素将在数据结构中留下空位。
FoodMap.Remove(6);
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  ,
 *  { Key:7, Value:"Cake" }]
*/

// 使用 FindAndRemoveChecked 函数可用于从映射移除元素并返回其值,不存在,则出现断言。
FString RemovedStr = FoodMap.FindAndRemoveChecked(7); // ==> RemovedStr == Cake
FString RemovedStr = FoodMap.FindAndRemoveChecked(7); // ==> Assert
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  ,
 *  ]
*/
 
// 使用 RemoveAndCopyValue 函数的作用与 Remove 相似,不同点是会将已移除元素的值复制到引用。
// 如果映射中不存在指定的键,函数将返回 false。
FString RemovedStrA;
bool bExistA = FoodMap.RemoveAndCopyValue(3, RemovedStrA); // ==> bExistA  == true; RemovedStrA  == "Orange"
/** 当前TMap为:
 * FoodMap == [
 *  ,
 *  ,
 *  ]
*/
FString RemovedStrB;
bool bExistB = FoodMap.RemoveAndCopyValue(1, RemovedStrB); // ==> bExistB  == false; RemovedStrB  == ""
/** 当前TMap为:
 * FoodMap == [
 *  ,
 *  ,
 *  ]
*/

// 使用 Empty 或 Reset 函数可将映射中的所有元素移除。
// Reset 则是尽可能多地留出slack量。
FoodMap.Empty();
/** 当前TMap为:
 * FoodMap == [
 *  ,
 *  ,
 *  ]
*/
FoodMap.Reset();
/** 当前TMap为:
 * FoodMap == []
*/



//======================================================================================
//改
//运算符
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/

// 使用 [] 去更改值。
FoodMap[7] = TEXT("Cola");
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cola" }]
*/

// 使用 MoveTemp 函数可调用移动语义,在移动后,源映射为空。
TMap NewFoodMap;
NewFoodMap = MoveTemp(FoodMap);
/** 当前TMap为:
 * NewFoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cola" }]
 * FoodMap == []
*/
//排序
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/

// 使用 KeySort 或 ValueSort 函数可分别按键和值进行排序,皆可使用Lambda谓语。
FoodMap.KeySort([](int32 A, int32 B) {
    return A > B;
});
/** 当前TMap为:
 * FoodMap == [
 *  { Key:7, Value:"Cake" },
 *  { Key:6, Value:"Apple" },
 *  { Key:3, Value:"Orange"}]
*/

FruitMap.ValueSort([](const FString& A, const FString& B) {
    return A.Len() > B.Len();
});
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/
//内存
TMap FoodMap;
/** 当前TMap为:
 * FoodMap == []
*/

// 使用 Reserve 函数预先分配映射
FoodMap.Reserve(3);
/** 当前TMap为:
 * FoodMap == [
 *  ,
 *  ,
 *  ]
*/

// 使用 Shrink 函数可移除 TMap 中的全部 Slack。
FoodMap.Shrink();
/** 当前TMap为:
 * FoodMap == []
*/

// Shrink 将从容器的末端移除所有Slack,通常会留下空白元素。
// 使用 Compact 函数将空白空间组合在一起,为调用 Shrink 做好准备。
/** 假设当前TMap为:
 * FoodMap == [
 *  ,
 * { Key:3, Value:"Orange"},
 *  ,
 * { Key:6, Value:"Apple" },
 *  ,
 * { Key:7, Value:"Cake" }
 *  ]
*/
FoodMap.Shrink();
/** 当前TMap为:
 * FoodMap == [
 *  ,
 * { Key:3, Value:"Orange"},
 *  ,
 * { Key:6, Value:"Apple" },
 *  ,
 * { Key:7, Value:"Cake" }]
*/
FoodMap.Compact();
/** 当前TMap为:
 * FoodMap == [
 * { Key:3, Value:"Orange"},
 * { Key:6, Value:"Apple" },
 * { Key:7, Value:"Cake" },
 *  ,
 *  ,
 *  ]
*/
FoodMap.Shrink();
/** 当前TMap为:
 * FoodMap == [
 * { Key:3, Value:"Orange"},
 * { Key:6, Value:"Apple" },
 * { Key:7, Value:"Cake" }]
*/



//======================================================================================
//查
/** 当前TMap为:
 * FoodMap == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"Cake" }]
*/

// 使用 Num 函数查询映射中保存的元素数量。
int32 Count = FoodMap.Num(); // ==> Count == 3

// 使用 Contains 函数查询是否包含特定键。
bool bHas = FoodMap.Contains(7); // ==> bHas == true
bool bHas = FoodMap.Contains(1); // ==> bHas == false

// 使用 [] 运算符将键用作索引查找相应值。
// 在使用运算符 [] 前,应检查映射中是否 Contains 该键,如果映射中键不存在,将触发断言。
FString Str = FoodMap[7]; // ==> Str == "Cake"

// 使用 Find 函数进行键查找,
// 如果映射包含该键,Find 将返回指向元素数值的指针,如果映射不包含该键,则返回 nullptr。
FString* Str = FoodMap.Find(7); // ==> *Str == "Cake"
FString* Str = FoodMap.Find(10); // ==> Str == nullptr

// 使用 FindOrAdd 将返回给定键的值引用。
// 如果映射中不存在该键,FindOrAdd 将返回新创建的元素。
// FindOrAdd 可修改映射,因此仅适用于非常量映射。
FString& Str = FoodMap.FindOrAdd(7);
Str = "";
FString& Str = FoodMap.FindOrAdd(8);
Str = "Cake";

/** 当前TMap为:
 * FoodMapA == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"" },
 *  { Key:8, Value:"Cake" },]
*/

// 使用 FindRef 会返回与给定键关联的值副本。
// 若映射中未找到给定键,则返回默认构建值。
// FindRef 不会创建新元素,因此既可用于常量映射,也可用于非常量映射。
FString Str = FoodMap.FindRef(8); // ==> Str == "Cake"
Str = TEXT("Apple"); // ==> Str == "Apple"

/** 当前TMap为:
 * FoodMapA == [
 *  { Key:3, Value:"Orange"},
 *  { Key:6, Value:"Apple" },
 *  { Key:7, Value:"" },
 *  { Key:8, Value:"Cake" },]
*/

// 使用 FindKey 函数执行逆向查找。
// 返回指向提供值配对的第一个键的指针,搜索映射中不存在的值将返回空键。
// 按值查找比按键查找慢。
const int32* KeyA = FoodMap.FindKey(TEXT("Apple"));   // *KeyA   == 6
const int32* KeyB = FoodMap.FindKey(TEXT("Cola")); //  KeyB == nullptr

// 使用 GenerateKeyArray 和 GenerateValueArray 分别使用所有键和值的副本来填充到 TArray。
TArray   FoodKeys;
TArray FoodValues;
FoodMap.GenerateKeyArray(FoodKeys);
FoodMap.GenerateValueArray(FoodValues);
// FoodKeys   == [ 3,6,7,8 ]
// FoodValues == [ "Orange","Apple","Pineapple","Cake" ]

//遍历操作。(注意:遍历时不要做删除操作)
// auto 遍历
for (auto& Elem :FoodMap)
{
    Elem.Key;	// Map的Key
	Elem.Value;	// Map的Value
}

// 迭代器遍历
// CreateIterator 返回拥有读写访问权限的迭代器,
// CreateConstIterator 返回拥有只读访问权限的迭代器
for (auto It = FoodMap.CreateConstIterator(); It; ++It)
{
	It.Key();	// Map的Key
	It.Value();	// Map的Value
}

你可能感兴趣的:(C++,UE5学习笔记,UE,C++)