用Java实现MVPtree——MVPtree点集内去重以及衍生出来的多维向量Hash问题
上次完成了MVPtree之后,客户又提出了MVPtree点集元素重复的问题,希望我将元素去重。
集合去重哪家强?java.util找HashSet!如果不计较元素顺序,放进去基本就没有重复元素了。
只是这样的话就要重写equals()和hashCode()函数(方法)。因为equals()默认是比较指针(引用)的,2个不同时间new的元素指针不同,就算内部元素相同也会被判定为不同,一定要重写。hashCode()更加难搞,如果没有写好,hash数组会出现只有少数数组下标占有数据的情况,那样hash表会退化为链表。
一般用在MVPtree的数据都是二维点、三维点,或者多维点数据。由于一个维度的坐标数不可能无限大,可以把向量当做N进制数,N就是维度的坐标数最大可达多少。但是很多点是用浮点数的,double可容纳16位小数,整数部分可达10的308次方,如果以最大范围为基准确定N,要用大数类BigInteger不说,hash值可能会撑爆。所以按照一个维度实际可达范围确定N。
例如有一个4维点,小数精确到6位,维度范围是[-400,500],N就可取900*1000(忽略后3位小数的不同),取模前的hash值是hash( (a,b,c,d) ) = hash( (a,b,c) )*900000 + hash(d),hash( (a,b,c) ) = hash( (a,b) )*900000 + hash(c),以此类推。其中hash(a) = a + 400,在点较为分散的时候不容易扎堆。
如果点过于集中,N一定要取大一些,以更好地打散点集。
还要对hash值取模,不然值太大了内存根本找不到合适的地址,访问失败。一般这个模数是素数(容易打散数据),比原数组大一点。
-------------------------------我是分割线------------------------------------
代码地址:https://coding.net/u/funcfans/p/MVPtree-for-Java/git