JAVA面试-HahMap/HashTable/ConcurrentHashMap

本文深入探讨了HashTable、HashMap与ConcurrentHashMap三种Java集合框架中的Map实现。详细对比了它们的数据结构、线程安全性、初始容量、扩容策略及计算索引的方式。特别强调了ConcurrentHashMap通过分段锁提高并发性能的机制。

HashTable

底层数组+链表实现,key 和 value不能为null,线程安全的;

初始size为11,扩容:newsize = oldsize*2 + 1;

计算index:index = (hash & ox7FFFFFFF)%tab.length;

 

HashMap

底层数组+链表实现,可以存储null键和null值,线程不安全;

初始size为16,扩容:newsize = oldsize*2;

扩容针对整个Map,每次扩容时,原来数组中的元素,依次重新计算存放位置,并重新插入;

当map中元素总数超过Entry数组75%,触发扩容操作;

计算index:index = hash & (tab.length -1 );

 

ConcurrentHashMap

底层采用分段数组+链表实现,线程安全;

通过把整个map分为N个segment,可以提供相同的线程安全,但是效率提升了N倍,默认提升16倍。(读操作不加锁,是由于HashEntry的value变量是volatile,能够保证读取到最新的值);

HashTable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁的分类技术;

size()和containsValue(),需要锁定整个表而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后按顺序释放所有段的锁;

段内扩容(段内元素超过该段对应的entry数组长度75%,触发扩容,而不会对整个map扩容),插入前检测需不需要扩容,有效避免无效扩容;

HashMap和ConcurrentHashMap都实现了Map接口,HashTable实现的是基于Dictionary抽象类。

你遇到的错误是典型的 **链接错误(Linker Error)**,具体表现为: ``` undefined reference to `create_drone_hashtable` undefined reference to `print_all_drones` undefined reference to `destroy_drone_hashtable` undefined reference to `get_drone_count` ``` 这些函数在 `app.c` 中被调用了,但链接器找不到它们的定义。也就是说:**声明了函数,却没有实现(定义)这些函数,或者实现了但没有参与编译和链接。** --- ### ✅ 问题原因分析 1. **函数未定义** 你在 `app.c` 或其他头文件中使用了如下类似函数: ```c create_drone_hashtable(); print_all_drones(); destroy_drone_hashtable(); get_drone_count(); ``` 但你在任何 `.c` 文件中都没有提供这些函数的实际实现。 2. **函数定义了,但源文件未加入编译** 比如你写了 `drone_hashtable.c` 实现了上述函数,但在 `Makefile` 中没有将其加入编译列表。 3. **跨平台交叉编译路径问题(aarch64)** 你正在使用 `aarch64-linux-gnu-gcc` 进行交叉编译,但如果 `hashtable` 相关代码只适用于 x86 平台或未正确包含,也可能导致遗漏。 --- ### ✅ 解决方案 #### 步骤 1:确认是否缺少 `hashtable` 模块的实现 你需要创建一个专门处理无人机哈希表的模块,例如: ##### `hashtable.h` ```c #ifndef HASHTABLE_H #define HASHTABLE_H // 假设每个 drone 是一个结构体 typedef struct { char id[32]; float latitude; float longitude; int battery_level; } Drone; // 哈希表操作函数声明 void create_drone_hashtable(void); void destroy_drone_hashtable(void); void print_all_drones(void); int get_drone_count(void); // 可选:添加/查找等接口 Drone* find_drone(const char* id); void add_drone(const char* id, float lat, float lon, int bat); #endif ``` ##### `hashtable.c` ```c #include "hashtable.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #define TABLE_SIZE 100 // 简单链式哈希表节点 typedef struct DroneNode { Drone data; struct DroneNode* next; } DroneNode; static DroneNode* hash_table[TABLE_SIZE] = { NULL }; // 简单哈希函数 unsigned int hash(const char* id) { unsigned int hash_val = 0; while (*id) { hash_val = (hash_val << 5) + *id++; } return hash_val % TABLE_SIZE; } // 创建哈希表(初始化) void create_drone_hashtable(void) { // 静态数组已初始化为 NULL,这里可以留空或打印日志 printf("Drone hashtable initialized.\n"); } // 销毁哈希表,释放内存 void destroy_drone_hashtable(void) { for (int i = 0; i < TABLE_SIZE; i++) { DroneNode* node = hash_table[i]; while (node != NULL) { DroneNode* temp = node; node = node->next; free(temp); } hash_table[i] = NULL; } printf("Drone hashtable destroyed.\n"); } // 打印所有无人机信息 void print_all_drones(void) { printf("=== Current Drones ===\n"); int count = 0; for (int i = 0; i < TABLE_SIZE; i++) { DroneNode* node = hash_table[i]; while (node != NULL) { printf("ID: %s, Pos: (%.6f, %.6f), Battery: %d%%\n", node->data.id, node->data.latitude, node->data.longitude, node->data.battery_level); count++; node = node->next; } } printf("Total drones: %d\n", count); } // 获取当前无人机数量 int get_drone_count(void) { int count = 0; for (int i = 0; i < TABLE_SIZE; i++) { DroneNode* node = hash_table[i]; while (node != NULL) { count++; node = node->next; } } return count; } // 查找无人机 Drone* find_drone(const char* id) { unsigned int idx = hash(id); DroneNode* node = hash_table[idx]; while (node != NULL) { if (strcmp(node->data.id, id) == 0) { return &node->data; } node = node->next; } return NULL; } // 添加无人机(若已存在则更新) void add_drone(const char* id, float lat, float lon, int bat) { unsigned int idx = hash(id); DroneNode* node = hash_table[idx]; while (node != NULL) { if (strcmp(node->data.id, id) == 0) { // 更新已有 node->data.latitude = lat; node->data.longitude = lon; node->data.battery_level = bat; return; } node = node->next; } // 插入新节点 DroneNode* new_node = malloc(sizeof(DroneNode)); if (!new_node) { fprintf(stderr, "Memory allocation failed\n"); return; } strcpy(new_node->data.id, id); new_node->data.latitude = lat; new_node->data.longitude = lon; new_node->data.battery_level = bat; new_node->next = hash_table[idx]; hash_table[idx] = new_node; } ``` --- #### 步骤 2:修改 Makefile,确保 `hashtable.c` 被编译并链接 你的 `Makefile` 应该类似这样(关键部分): ```makefile CC = aarch64-linux-gnu-gcc CFLAGS = -Wall -O2 -I./include -I. LDFLAGS = OBJS = app/app.o hashtable.o TARGET = at606_app $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS) hashtable.o: hashtable.c hashtable.h $(CC) $(CFLAGS) -c hashtable.c -o hashtable.o clean: rm -f $(OBJS) $(TARGET) .PHONY: clean ``` > 注意:如果你把 `hashtable.c` 放在 `src/` 或 `common/` 目录下,请调整路径和目标名,比如 `common/hashtable.o`。 --- #### 步骤 3:在 `app.c` 中包含头文件 确保在 `app.c` 开头包含了: ```c #include "hashtable.h" ``` 这样才能正确调用 `create_drone_hashtable()` 等函数。 --- ### ✅ 最终效果 完成以上步骤后: 1. `hashtable.c` 提供了缺失函数的实现; 2. `Makefile` 将其编译为 `hashtable.o` 并参与链接; 3. 链接器能找到所有符号,不再报 `undefined reference` 错误; 4. 程序可以成功构建用于 aarch64 平台。 --- ### 🔍 补充建议 - 使用 `nm hashtable.o` 或 `objdump -t hashtable.o` 检查目标文件是否导出了对应函数。 - 若使用 IDE 或 CMake,也要确保源文件被加入项目。 - 对于大型项目,推荐将通用模块(如 hashtable)编译成静态库(`.a`),便于复用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值