Java 哈希表包含无法正常工作的值

Java 哈希表包含无法正常工作的值,java,hashtable,Java,Hashtable,我有一个巨大的浮点数组,我必须从中删除重复项。我试图创建一个哈希表来填充唯一的值,并将其传递回另一个数组并返回。问题在于containsValue方法,它总是返回false,因此所有点都添加到哈希表中 private float[] removeDuplicates1(float[] input){ Hashtable<Integer, float[]> h= new Hashtable<>(); for(int i=0; i<input.lengt

我有一个巨大的浮点数组,我必须从中删除重复项。我试图创建一个哈希表来填充唯一的值,并将其传递回另一个数组并返回。问题在于containsValue方法,它总是返回false,因此所有点都添加到哈希表中

private float[] removeDuplicates1(float[] input){
    Hashtable<Integer, float[]> h= new Hashtable<>();
    for(int i=0; i<input.length/3; ++i) {
        float[] pt= new float[]{input[i * 3], input[i * 3 + 1], input[i * 3 + 2]};
        Log.i(TAG, Float.toString(pt[0]) + " " +Float.toString(pt[1]) + " " +Float.toString(pt[2]));  //ok
        Log.i(TAG, Boolean.toString(h.containsValue(pt)));      //always false !?
        if(!(h.containsValue(pt))){
            h.put(i,pt);
            Log.i(TAG, "added");
        }
        else Log.i(TAG, "NOT added");
    }
    float[] whitelist = new float[h.size()*3];
    int a=0;
    for(int j=0; j<h.size(); j++){
        float[] f= h.get(j);
        whitelist[a]= f[0];
        whitelist[a+1]= f[1];
        whitelist[a+2]= f[2];
        a=a+3;
    }
    return whitelist;
}
private float[]removeDuplicates1(float[]input){
Hashtable h=新的Hashtable();
for(int i=0;i
h.containsValue(pt)
在查找匹配项时比较数组的地址,而不是它们的内容

为了实现您想要的功能,您可以编写一个包装类作为映射中的值,并为其覆盖
equals
hashcode

h.containsValue(pt)
在查找匹配项时比较数组的地址,而不是数组的内容

为了实现您想要的,您可以编写一个包装类作为映射中的值,并为其重写
equals
hashcode

private float[] removeDuplicates1(float[] input){
    Hashtable<Integer, Point> h= new Hashtable<>();
    int hn=0;
    for(int i=0; i<input.length/3; ++i) {
        Point pt= new Point(input[i * 3], input[i * 3 + 1], input[i * 3 + 2]);
        Log.i(TAG, Float.toString(pt.x) + " " +Float.toString(pt.y) + " " +Float.toString(pt.z));
        Log.i(TAG, Boolean.toString(h.containsValue(pt)));
        if(!(h.containsValue(pt))){
            h.put(hn,pt);
            hn++;
            Log.i(TAG, "added");
        }
        else Log.i(TAG, "NOT added");
    }
    float[] whitelist = new float[h.size()*3];
    int a=0;
    for(int j=0; j<h.size(); ++j){
        Point p = new Point(h.get(j));
        whitelist[a] = p.x;
        whitelist[a + 1] = p.y;
        whitelist[a + 2] = p.z;
        a = a + 3;
    }
    return whitelist;
}
解决


基本上,你是在问一个数组是否等于另一个数组。这永远不会是真的-数组不会覆盖
equals
。看起来你的输入实际上是一个三元组的集合-听起来你应该用三个
float
字段构造一个类(我们无法真正说出它们的含义)适当地覆盖
等于
。还要注意
哈希表。containsValue
基本上是一个O(n)查找-这是一个非常糟糕的重复数据消除选择。containsValue使用equals方法进行比较,两个数组永远不相等。别忘了覆盖
hashCode()
也一样,因为您想使用哈希表,所以它只比较具有相同哈希代码的对象。最简单的哈希代码是数组的长度。基本上,您要问的是一个数组是否等于另一个数组。这永远不会是真的-数组不会覆盖
等于
。看起来您的输入实际上是一个集合关于三元组-听起来你应该用三个
float
字段构造一个类(我们真的不知道它们是什么意思),这些字段适当地覆盖
等于
。还要注意
哈希表。containsValue
基本上是一个O(n)查找-这是一个非常糟糕的重复数据消除选择。containsValue使用equals方法进行比较,两个数组永远不相等。别忘了重写
hashCode()
也是,因为您想使用哈希表,所以它只比较具有相同哈希代码的对象。在您的情况下,最简单的哈希代码是arry的长度。好的,我知道我必须为float[]创建一个包装器对象类要点,但我不明白hashcode是什么以及它是如何工作的。你能给我举个例子吗?
hashcode
契约在类对象的javadoc中描述:部分联系是:“•如果两个对象根据相等(对象)是相等的方法,然后对两个对象中的每个对象调用hashCode方法必须生成相同的整数结果”,这就是为什么在重写
equals
时总是要重写它的原因。Eclipse有一个基于类的成员生成这两个方法的选项。好的,我知道我必须为float[]创建一个包装器对象类要点,但我不明白hashcode是什么以及它是如何工作的。你能给我举个例子吗?
hashcode
契约在类对象的javadoc中描述:部分联系是:“•如果两个对象根据相等(对象)是相等的方法,然后对两个对象中的每一个调用hashCode方法必须生成相同的整数结果”,这就是为什么在重写
equals
时总是要重写它的原因。Eclipse有一个基于类成员生成这两个方法的选项。
public class Point {
    public float x;
    public float y;
    public float z;

    public Point(float x, float y, float z){
        this.x=x;
        this.y=y;
        this.z=z;
    }

    public Point(Point p){
        this.x=p.x;
        this.y=p.y;
        this.z=p.z;
    }

    @Override
    public boolean equals(Object o){
        final Point p = (Point) o;
        if((p.x==this.x) && (p.y==this.y) && (p.z==this.z)) return true;
        else return false;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + Float.floatToIntBits(this.x);
        hash = 53 * hash + Float.floatToIntBits(this.y);
        hash = 53 * hash + Float.floatToIntBits(this.z);
        return hash;
    }
}