我在Processing.js中迭代一个Processing.js时遇到了问题。调用迭代器时,不会输入while(it.hasNext())。
作为正常检查,我尝试跳过迭代器,而是将键转换为数组并按索引迭代这些键。那也没用。我打印了以下内容:
myHashMap.size(); // outputs 4
myHashMap.keySet().size(); // outputs 4
myHashMap.keySet().toArray().length; // outputs 0我希望最后一行也能输出4,就像他们以前调用的那样。我是不是理解错了什么?谢谢!
编辑
下面是我遇到的问题的一个完整例子。结果发现,在我的HashCode中使用浮点是一个问题,尽管我仍然不明白为什么在将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发布于 2016-04-08 02:11:08
我想我终于明白了。这有点让人抓狂。问得好。
这个故事的寓意:我认为你在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's 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。
我不认为这是一个错误,因为这个问题是由从一个函数返回一个float引起的,该函数表示它将返回一个int。JavaScript并不像Java那样真正需要hashCode()函数,因此HashMap和Iterator的这种实现是相当合理的。您只需确保从int函数返回一个hashCode()。
顺便提一句,下面是一个小例子,如果你想玩一玩的话:
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
}https://stackoverflow.com/questions/36487074
复制相似问题