ArkTs学习之Map 对象, Map与字典的区别, Map 与 Record的区别

一、Map 对象

1. Map的基础操作

🔊:初始化Map的键和值,它们可以是任何类型, 注意Map中所有的键或所有的值必须是相同类型

TypeScript 使用 Map 类型 和 new 关键字来创建 Map:

let myMap = new Map();

但是,在ArkTs中我们需要明确具体的类型,不然会报错

let myMap = new Map(); //🙅错误:Use explicit types instead of "any", "unknown" (arkts-no-any-unknown) <ArkTSCheck>
let myMap1 = new Map<string,string>() //🙆正确:明确了具体Map中键值对的类型,为[string,string]

初始化 Map,也可以以数组的格式来传入键值对:

let myMap = new Map([
 ["key1", "value1"],
 ["key2", "value2"]
]);

🔊:通过map.set设置键值对,返回该Map对象

myMap.set("key3", 'value3')
console.log(myMap)

🔊:通过map.get获取键对应的值,如果不存在,则返回undefined

let getmap = myMap.get("key1")
let getmap2 = myMap.get("key999")
console.log(getmap); //'value1'
console.log(getmap2); //undefine

🔊:通过map.delete()删除键值对,删除则返回true,未删除则返回false

let deletemap = myMap.delete("key2")
let deletemap1 = myMap.delete("key999")
console.log(`${deletemap}`) // true
console.log(`${deletemap1}`); // false

🔊:通过map.has()判断 Map中是否包含所查找的键值,返回布尔型

let hasmap = myMap.has("key1")
let hasmap2 = myMap.has("key2")
console.log(`${hasmap}`)  //true
console.log(`${hasmap2}`) //true

🔊:通过map.clear()移除所有键值对,清除Map。无法返回值

let clearmap = myMap.clear()
console.log(`${clearmap}`)  //undefine
console.log(`${myMap}`)  // 空 [object Map] 对象

🔊:通过map.size 获取对象键/值对的数量。返回number型

let sizemap = myMap.size
console.log(`${sizemap}`) //2

🔊:map.keys() - 返回一个 Iterator 对象, 包含了 Map 对象中每个元素的键 。

let keysmap = myMap.keys()
console.log(`${keysmap}`) // 所有的keys:[object Map Iterator]

🔊:map.values() – 返回一个新的Iterator对象,包含了Map对象中每个元素的值 。

let valuesmap = myMap.values()
console.log(`${valuesmap}`) // 所有的values:[object Map Iterator]

2. Map的迭代

Map的迭代有多种方式

🔊 1. 使用for...of进行迭代,返回一个包含键值对的数组

let myMap = new Map<number,string>([
   [0,'zero'],
   [1,'zero']
])
    
//🙅错误:arkTs不支持 Destructuring variable declarations are not supported (arkts-no-destruct-decls) <ArkTSCheck>
for (let [key,value] of myMap) {
    console.log(`key:${key}--value:${value}`)
}
    
//🙆正确:可以获取myMap中的具体的元组map,然后再根据索引获取
for (let map of myMap){
   console.log(`key:${map[0]}--value:${map}[1]`)
}

🔊 2. 使用forEach进行迭代,它会接受一个回调函数作为参数

let myMap = new Map<number,string>([
    [0,'zero'],
    [1,'zero']
])

//通过foreach 迭代
myMap.forEach((key,value)=>{
    console.log(`key:${key}--value:${value}`)
})

🔊 3. 使用 keys 方法迭代所有的键

let myMap = new Map<number,string>([
    [0,'zero'],
    [1,'zero']
])

//通过keys 迭代出所有key
for (let key of myMap.keys()) {
    console.log(`${key}`)
}

🔊 4. 使用 values 方法迭代所有的值

let myMap = new Map<number,string>([
    [0,'zero'],
    [1,'zero']
])

//通过values 迭代出所有value
for (let value of myMap.values()) {
    console.log(`${value}`)
}

⚠️:需要注意的是,使用 for...of 或 forEach 迭代时,键值对的顺序与添加顺序一致;而使用 keys 或 values 迭代时,顺序与添加顺序无关。

二、Map 与 字典 的区别

对于上面两个数据,有以下区别

🔊 1. 数据类型

statusColorMap1 是一个普通的JavaScript对象。
statusColorMap2 是一个Map对象。

🔊 2. 键的类型

statusColorMap1 的键是数值(number)类型。
statusColorMap2 的键是字符串(string)类型,即使你在初始化时写的是数字,但在Map中它们会被自动转换为字符串。

🔊 3. 键的排序

普通对象的键是无序的,这意味着你不能期望遍历对象的属性时总是以特定的顺序获得它们(尽管在大多数现代浏览器中,当你以特定的顺序插入属性时,它们会按该顺序返回,但这并不是规范所保证的)。
Map对象的键是按照插入顺序排序的。

🔊 4. 键和值的获取

使用statusColorMap1[key]来获取或设置对象的值。
使用statusColorMap2.get(key)来获取Map的值,使用statusColorMap2.set(key, value)来设置值。

🔊 5. 键的存在性检查

对于对象,你可能需要使用key in object来检查键是否存在。
对于Map,你可以使用map.has(key)来检查键是否存在。

🔊 6. 迭代

你可以使用for...in循环(但要小心原型链上的属性)或Object.keys(), Object.values(), Object.entries()等方法来迭代对象的键和值。
对于Map,你可以使用for...of循环直接迭代其键-值对,或者使用map.keys(), map.values(), map.entries()等方法来获取迭代器。

🔊 7. 大小:

对于对象,你需要使用Object.keys(object).length来获取其大小(即属性的数量)。
对于Map,你可以使用map.size属性来获取其大小。

🔊 8. 其他方法和特性:

Map对象提供了许多其他方法和特性,如clear()(清除所有键-值对)、delete(key)(删除指定键的键-值对)等,这些在普通对象中是没有的(除非你自己实现这些方法)。

总的来说,选择使用对象还是Map取决于你的具体需求。如果你需要有序的键、更方便的迭代或更多的方法,那么Map可能是一个更好的选择。但是,如果你只是需要简单的键值对存储,并且不关心键的排序或迭代顺序,那么对象可能就足够了。

三、Map 与 Record的区别

1. Map 与 Record 两者的区别

🔊 Record<string, string>

定义: Record 是 TypeScript 的一种类型,用于表示一个对象,其中所有的键是特定类型(通常是 string 或 number),所有的值也是特定类型。

语法:

const record: Record<string, string> = {
  "key1": "value1",
  "key2": "value2"
};

特性:

Record 用于描述对象的结构和类型。
对象的键是字符串(或其他类型如数字),值的类型是固定的。
适合描述静态且结构固定的键值对集合。
不提供内建的方法来操作数据,如 .set(), .get() 等。

🔊 Map<string, string>

定义: Map 是 JavaScript 内建的数据结构,用于存储键值对,其中键和值都可以是任意类型(在这里是 string 类型)。

语法:

const map = new Map<string, string>([
  ["key1", "value1"],
  ["key2", "value2"]
]);

特性:

Map 是一个类,提供了丰富的方法来操作键值对,比如 .set(), .get(), .delete(), .has(), .clear()。
保持键值对的插入顺序,并可以通过迭代来访问。
键和值的类型可以是任何类型,但在这个例子中是 string。
Map 提供了更灵活的数据操作能力和性能优化(如基于哈希的查找效率)。

🔊 总结

Record: 用于描述对象的固定结构和类型。适合静态数据和简单的键值对存储。
Map: 更加灵活的数据结构,适用于动态操作和需要保持插入顺序的键值对集合。提供了内建的操作方法。

2. MapRecord 类型转换函数

在HarmonyOS中,Record 类型提供了一种方便的方式来定义具有特定键值对结构的对象。然而,Record 本身没有直接修改其元素的内置方法,但是我们可以借助 Map 类型来实现对 Record 数据的增删改操作,然后再转换回 Record 类型。

🔊 Map 转为 Record

在 TypeScript 中,我们定义了 mapToRecord 函数来实现从 MapRecord 的转换。

// Map转为Record 
export function mapToRecord(myMap: Map<string, string>): Record<string, string> { 
  return Object.fromEntries(myMap.entries()) as Record<string, string>; 
} 

这个函数利用了 Object.fromEntries 方法,它接受一个可迭代对象(这里是 Mapentries 方法返回的迭代器),并将其转换为一个普通对象。然后通过类型断言将其转换为 Record<string, string> 类型。

🔊 Record 转为 Map

相应地,recordToMap 函数用于将 Record 转换为 Map

// Record转为Map 
export function recordToMap(myRecord: Record<string, string>): Map<string, string> { 
  let myMap: Map<string, string> = new Map(); 
  for (const key in myRecord) { 
    myMap.set(key, myRecord[key]); 
  } 
  return myMap; 
}

该函数遍历 Record 对象的键,将每个键值对添加到新创建的 Map 中,最后返回这个 Map

3. 在 ArkTS 中操作 Record 数据

在 ArkTS 项目中,首先导入上述定义的转换函数。

import { mapToRecord, recordToMap } from './utils'; 

接着定义一个初始的 Record 对象 res

let res: Record<string, string> = { 'item1': '1', 'item2': '2' }; 

然后将其转换为 Map 类型,以便进行增删操作。

let myMap: Map<string, string> = recordToMap(res); 
myMap.set('item3', '3'); // 添加元素 
myMap.delete('item1'); // 删除元素 

在添加元素时,使用 Mapset 方法添加一个新的键值对 'item3': '3';删除元素则通过 delete 方法删除键为 'item1' 的键值对。

最后,再将修改后的 Map 转换回 Record 类型。

let myRecord = mapToRecord(myMap);

Index 组件的 build 函数中,当点击按钮时,将修改后的 Record 对象以 JSON 字符串的形式输出到控制台。

@Entry 
@Component 
struct Index { 
  build() { 
    Row() { 
      Column() { 
        Button('change Record') 
         .onClick(() => { 
            console.log('myRecord:', JSON.stringify(myRecord)); // myRecord: {"item2":"2","item3":"3"} 
          }) 
      } 
     .width('100%') 
    } 
   .height('100%') 
  } 
}

posted on 2025-02-10 14:27  梁飞宇  阅读(1084)  评论(0)    收藏  举报