java - 为 Map/Associative Array 数据结构实现 put(或 add)方法
问题描述
我得到一个带有通用类型 (K,V) 的 Map 数据结构,其中 K 代表键,V 代表值。
现在我被要求实现经典的put(K key, V value)方法,该方法随集合一起提供。该方法是预先实现的,并从所使用的接口覆盖一个:
@Override
public void put(K key, V value) {
for (int i = 0; i <= this.entries.length; i++) {
if (this.entries[i] == null || this.entries[i].getKey().equals(key)) {
this.entries[i] = new Entry<K, V>(key, value);
return;
} else {
this.entries = GenericArrayHelper.copyArrayWithIncreasedSize(this.entries, (this.entries.length) * 2);
/* replace [...]
this.entries[...] = new Entry<K, V>(key, value);
*/
}
}
}
除了被注释掉的部分,我需要用数组的正确位置替换 [...] 。即:
如果映射中索引 i 处的 Entry<K,V> 为空,或者索引 i 处的条目的键等于传递的键,则将该条目替换为包含传递的键和值的新条目,并完成该方法。
如果找不到这样的 Entry<K,V>,则应完整复制调用该方法的映射(其形式为 entries<K,V>[ ] 的数组),其数组大小应为加倍(使用辅助方法GenericArrayHelper.copyArrayWithIncreasedSize)。随后,在复制和调整大小的数组的第一个空槽处,使用传递的键和值放入一个新条目。
这就是产生混乱的地方。我试图用各种索引替换 [...],但从未得到令人满意的结果。
当我尝试输入这几个条目时,putInside是一个 Map:
putInside.put("sizeInMB", 42);
putInside.put("version", 4);
putInside.put("yearOfRelease", 2015);
打印时(使用单独的 toString 方法“字符串化”),我将得到以下结果:
yearOfRelease : 2015
sizeInMB : 42
version : 4
yearOfRelease : 2015
sizeInMB : 42
version : 4
但是当我说,使用entry.length-1的数组索引来表示 [...],这是我经过数小时的尝试后最接近的,并观察调试器,它看起来很糟糕:
前三个条目是正确的,但其他三个被混搭了......当我打印整个内容时,我只得到第一个树条目的输出,因为其他三个似乎完全被忽略了(也许是因为较大的for 循环中的数组仅在循环本身中定义?)
我的问题是:我如何为索引 [...] 定义一个合适的替代品,或者,也许也是为了更好地理解:为什么我们首先需要将数组的大小加倍?我以前从未实现过任何 Java Collection 数据结构,也没有在我的大学学习过数据结构类...... 我如何获得“双倍”输出?
任何形式的帮助都会非常感激!
编辑:为了让事情更清楚,这里是 toString 方法:
public static void toString(Map<String, Integer> print) {
for(String key : print.keysAsSet()){
System.out.println(key + ": " + print.getValueFor(key));
}
}
使用keysAsSet()返回 Map 的 HashSet,其中仅包含键,但不包含值。
public Set<K> keysAsSet() {
HashSet<K> current = new HashSet<>();
for(Entry<K,V> entry : entries){
if(entry != null) {
current.add(entry.getKey());
}
}
return current;
}
解决方案
代码与描述不符。也就是说,您正在调整循环内的数组大小,除非其中的第一个元素entries
是命中(即它是null
或它等于键)。
您需要在循环之后调整数组大小(加上修复循环条件检查):
@Override
public void put(K key, V value) {
int oldLength = this.entries.length;
for (int i = 0; i < oldLength; i++) {
if (this.entries[i] == null || this.entries[i].getKey().equals(key)) {
this.entries[i] = new Entry<K, V>(key, value);
return;
}
}
this.entries = GenericArrayHelper.copyArrayWithIncreasedSize(this.entries, oldLength * 2);
this.entries[oldLength] = new Entry<K, V>(key, value);
}
…我假设你知道这是一个非常低效的地图实现:每次搜索和插入都需要O ( n ) 次尝试。实际上,您可以使用哈希表或某种搜索树来加速插入和查找。
推荐阅读
- lodash - Lodash 使用 Alphanumberic 排序不正确?
- amazon-web-services - 如何在 Terraform 中为 SQS 使用 aws 提供的 kms 加密密钥
- python - PyQT5:为什么我的文件窗口会立即打开?
- python - Kafka:消息不以魔术字节开头
- javascript - 完成后再刮一次的最佳方法
- azure-devops - Azure DevOps Release Pipelines - 使用带句点的 env parms。在
- drupal-8 - 如何将视图行上的编号类设为静态?
- r - 如何在预测中使用重新缩放
- spring-boot - 如何使用 IDP 提供的公钥验证 saml [响应]
- swift - WKWebview 加载的页面无法正常交互