List Set Map - HimxhMC/HimDSL GitHub Wiki

List / Set / Map

三种容器 / Three Containers

数组适合"数量固定"的场景。数量可能变化时,用下面三种容器:

Arrays fit "fixed count". For changing counts, use these three:

  • List —— 有序、可重复,可以按下标访问。

  • Set —— 无序、不重复,只关心"在不在里面"。

  • Map —— 键值对,按键查值。

  • List — ordered, allows duplicates, indexed.

  • Set — unordered, no duplicates; "is it in there?".

  • Map — key-value pairs, look up by key.

它们都用 var 声明。泛型语法在 HimDSL 里不写。

All are declared with var. Generic syntax is not written in HimDSL.


创建容器 / Creating Containers

每种容器都有一个同名的内置函数:

Each container has a same-named built-in:

var list  = vector();       // 空的 List
var set   = set();          // 空的 Set
var m     = map();          // 空的 Map

注意 List 用的名字是 vector,不是 list——记住这一点。

Note: List's built-in is named vector, not list — remember that.


List:有序列表 / List: An Ordered List

添加 / Adding

var names = vector();
names.add("Steve");
names.add("Alex");
names.add("Herobrine");

读取 / Reading

按下标读取,从 0 开始:

Read by index, 0-based:

string first = names.get(0);     // "Steve"
string last = names.get(2);      // "Herobrine"

长度与空判断 / Length and Empty Check

int n = names.size();            // 3
bool empty = names.isEmpty();    // false

移除 / Removing

remove 有两种用法,看参数类型:

remove has two forms, depending on the argument type:

names.remove(0);                 // 按下标移除,返回被移除的元素
names.remove("Alex");            // 按值移除,返回是否成功

按下标移除时返回被移除的元素;按值移除返回布尔值。同一个方法,两种行为,注意区分。

By index: returns the removed element. By value: returns a boolean. One method, two behaviors — mind the difference.

查找 / Searching

bool has = names.contains("Alex");

遍历 / Iterating

for (int i = 0; i < names.size(); i = i + 1) {
    runcmd("CONSOLE", "say " + names.get(i));
}

Set:不重复集合 / Set: Unique Elements

Set 最常见的用途是自动去重:

The most common use of Set is automatic de-duplication:

var tags = set();
tags.add("vip");
tags.add("vip");            // 重复添加无效
tags.add("admin");

int n = tags.size();        // 2,不是 3

方法 / Methods

tags.add("staff");          // 添加
tags.remove("vip");         // 移除
bool has = tags.contains("admin");
int count = tags.size();
bool empty = tags.isEmpty();

遍历 / Iterating

Set 没有下标,不能 tags.get(0)。遍历时用另一个列表作为中转,或者把 Set 转为列表。

Sets have no indices; tags.get(0) is not supported. To iterate, use a list as an intermediary, or convert the Set to a list.

var arr = vector();
// 假设有 tags 的转换方法
// 或者从原始数据开始就用 vector

实践中,如果需要遍历,一开始就该用 vector。用 Set 只应该是因为"去重"是核心需求,且不需要按顺序访问。

In practice, if you need to iterate, start with vector. Reach for Set only when "no duplicates" is the core requirement and order does not matter.


Map:键值对 / Map: Key-Value Pairs

Map 用键查值。键和值可以是任何类型,但同一个 Map 里通常键的类型一致。

Maps look up values by key. Keys and values may be any type, but a given Map usually uses consistent key types.

写入与读取 / Writing and Reading

var ages = map();
ages.put("Steve", 25);
ages.put("Alex", 30);
ages.put("Herobrine", 99);

int a = ages.get("Steve");        // 25

判断键是否存在 / Key Existence

get 在键不存在时返回 null。要用 containsKey 明确区分 "值是 null" 和 "键不存在":

get returns null for missing keys. Use containsKey to distinguish "value is null" from "key missing":

bool has = ages.containsKey("Steve");   // true
bool missing = ages.containsKey("Bob"); // false

安全读取模式:

Safe-read pattern:

int a = 0;
if (ages.containsKey("Steve")) {
    a = ages.get("Steve");
}

移除 / Removing

ages.remove("Alex");        // 返回被移除的值,键不存在返回 null

空判断 / Empty Check

bool empty = ages.isEmpty();

Map 没有 size() 方法,判断是否为空用 isEmpty()。

Maps have no size(); test emptiness with isEmpty().


常见用法 / Common Patterns

统计出现次数 / Counting Occurrences

var counts = map();
var words = {"apple", "banana", "apple", "cherry", "apple"};

for (int i = 0; i < words.size(); i = i + 1) {
    string w = words.get(i);
    int c = 0;
    if (counts.containsKey(w)) {
        c = counts.get(w);
    }
    counts.put(w, c + 1);
}
// counts 中 apple → 3, banana → 1, cherry → 1

用 Map 做配置 / Map as Configuration

var config = map();
config.put("welcome", "欢迎光临");
config.put("farewell", "下次再见");

string msg = config.get("welcome");
runcmd("CONSOLE", "say " + msg);

列表去重 / De-duplicating a List

var raw = {"a", "b", "a", "c", "b"};
var seen = set();
var unique = vector();

for (int i = 0; i < raw.size(); i = i + 1) {
    string v = raw.get(i);
    if (!seen.contains(v)) {
        seen.add(v);
        unique.add(v);
    }
}
// unique 是 {"a", "b", "c"}

!seen.contains(v) 里的 ! 是逻辑非。这是"既要去重、又要保序"的常见写法。

The ! in !seen.contains(v) is logical negation. This is the usual pattern for "unique and order-preserving".


该选哪个 / Which to Choose

判断标准:

Decision:

  • 有序,允许重复 → vector

  • 只需要去重,不关心顺序 → set

  • 用键查值 → map

  • 数量固定 → 用数组

  • Ordered, duplicates allowed → vector

  • Only uniqueness matters → set

  • Look up by key → map

  • Fixed count → array

默认用 vector。只有在明确需要 Set 或 Map 的特性时才换。

Default to vector. Switch only when Set or Map offers a needed property.


小结 / Summary

  • 三种容器用 vector()、set()、map() 创建。

  • 都用 var 声明,不写泛型。

  • List:add / get / remove / contains / size / isEmpty。

  • Set:add / remove / contains / size / isEmpty。

  • Map:put / get / remove / containsKey / isEmpty。

  • Set 没有下标,需要遍历时考虑换 List。

  • Map 没有 size(),用 isEmpty()。

  • Create with vector(), set(), map().

  • Declare with var; no generics.

  • List: add / get / remove / contains / size / isEmpty.

  • Set: add / remove / contains / size / isEmpty.

  • Map: put / get / remove / containsKey / isEmpty.

  • Set has no indices; use a List if you need them.

  • Map has no size(); use isEmpty().


下一步 / Next Steps

下一章 Stack / Queue 介绍两种"有进出规则"的容器。

Next, Stack / Queue introduces two containers with strict in/out rules.