Processing.js HashMap
Processing.js HashMap
我在Processing.js中迭代HashMap时遇到问题。在调用迭代器时,永远不会输入while(it.hasNext())。
作为健全性检查,我尝试跳过迭代器,而是将键转换为数组,并通过索引对其进行迭代。这也没用。我打印出以下内容:
myHashMap.size(); // outputs 4
myHashMap.keySet().size(); // outputs 4
myHashMap.keySet().toArray().length; // outputs 0
我希望最后一行也能输出4,就像他们之前的调用一样。我是不是理解错误了?谢谢
编辑
这是我遇到的问题的一个完整的例子。在我的HashCode中使用float是个问题,尽管我仍然不明白为什么在将keySet转换为数组时会导致元素不匹配。
class Vertex {
float x;
float y;
public Vertex(float x, float y) {
this.x = x;
this.y = y;
}
public int hashCode() {
int hash = 17;
hash = ((hash + x) << 5) - (hash + x);
hash = ((hash + y) << 5) - (hash + y);
return hash
}
public boolean equals(Object obj) {
Vertex other = (Vertex) obj;
return (x == obj.x && y == obj.y);
}
}
HashMap<Vertex, String> tmp = new HashMap<Vertex, String>();
Vertex a = new Vertex(1.1, 2.2);
Vertex b = new Vertex(1, 1);
tmp.put(a, "A");
tmp.put(b, "B");
println("1, " + tmp.size()); // outputs 2
println("2, " + tmp.keySet().size()); // outputs 2
println("3, " + tmp.keySet().toArray().length); // outputs 1
我想我终于想通了。这让人有些挠头。问得好。
这个故事的寓意是:我想你对hashCode()
函数有点奇怪。hashCode()
函数必须返回int
值,但您返回的是float
值。
若要解决问题,请将hash
值强制转换为int
,然后再返回
public int hashCode() {
int hash = 17;
hash = ((hash + x) << 5) - (hash + x);
hash = ((hash + y) << 5) - (hash + y);
return (int)hash;
}
这可能看起来很奇怪,也没有必要,所以这里有一个更长的解释:
请注意,x
和y
是float
值,因此当您在hash
计算中使用它们时,结果也会变成float
。您可以在返回之前打印出hash
的值来证明这一点。
Java会对此抱怨。您可以通过切换到Java模式并尝试运行程序来证明这一点。但JavaScript对其类型没有那么严格,所以它会让你自食其果。我通常做的事情是在Java模式下进行编程,以进行错误检查,然后使用JavaScript模式进行部署。
无论如何,在HashMap
类中,hashCode()
函数的结果最终用作数组中的索引。您可以在Processing.js源文件中查看:
//this is in the HashMap class
function getBucketIndex(key) {
var index = virtHashCode(key) % buckets.length;
return index < 0 ? buckets.length + index : index;
}
function virtHashCode(obj) {
if (obj.hashCode instanceof Function) {
return obj.hashCode();
}
//other code omitted to keep this short
}
这可能很好,因为奇怪的是,JavaScript可以在数组索引中使用小数点。但问题在于HashSet
的Iterator
:的实现
function Iterator(conversion, removeItem) {
var bucketIndex = 0;
var itemIndex = -1;
var endOfBuckets = false;
var currentItem;
function findNext() {
while (!endOfBuckets) {
++itemIndex;
if (bucketIndex >= buckets.length) {
endOfBuckets = true;
} else if (buckets[bucketIndex] === undef || itemIndex >= buckets[bucketIndex].length) {
itemIndex = -1;
++bucketIndex;
} else {
return;
}
}
}
//more code
检查findNext()
的功能。它在数组的索引中循环,但每次递增一个。因此,任何放入小数点索引的键都将被跳过!
这就是迭代器跳过其中一个对象(从hashCode()
返回的值中有一个小数位的对象)的原因。这就是toArray()
也失败的原因,因为该函数在引擎盖下使用了Iterator
。
我不会真的称之为bug,因为问题是由一个函数返回float
引起的,该函数表示它将返回int
。JavaScript不像Java那样真正需要hashCode()
函数,所以HashMap
和Iterator
的实现非常合理。但您必须确保从hashCode()
函数返回int
。
顺便说一句,如果你想四处玩耍,这里有一个较小的例子:
class Thing {
int myThing;
public Thing(int myThing) {
this.myThing = myThing;
}
public int hashCode(){
return myThing;
}
public boolean equals(Object obj) {
Thing other = (Thing) obj;
return (myThing == other.myThing);
}
}
void setup() {
HashMap<Thing, String> map = new HashMap<Thing, String>();
map.put(new Thing(1), "A");
map.put(new Thing(2.5), "B"); //uh oh!
map.put(new Thing(3), "C");
println("1, " + map.size()); // outputs 3
println("2, " + map.keySet().size()); // outputs 3
println("3, " + map.keySet().toArray().length); // outputs 2
}
- 可以't让我的if语句处理js中的html表单输入
- 使用agility.js进行页面布局和合成
- 使用Clipboard.js复制span文本
- 使用JS如何动态更改显示的html文件中的文本背景颜色
- 强制模板刷新ember.js
- 如何编写HTML输入的JS内联
- Angular JS IE9 Hashbang url rewriting
- 使用JS将数组转换为json对象
- Node.js v6.2.0类扩展不是函数错误
- 当js函数's已执行
- 要求未定义JS回调参数
- 在自定义mean.io包中使用angular-chart.js作为依赖项
- 无法在数据endVal中设置值=“”;{{ucount}}”;使用Angular JS的CountUp
- 如何从Java/scala调用js美化程序
- 如何更改<svg>标记为<img>用js标记
- 如何使用 node.js 比较两个 json 数组
- chrome扩展:尽管运行了at:documentidle,js脚本还是过早启动
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- Processing.js HashMap
- Javascript/Node.js我可以使用hashmap有选择地执行函数吗?