Antonio Iacobucci
Antonio Iacobucci

Reputation: 59

HashTable containsValue not working properly

I have a huge float array and I have to remove duplicates from it. I tried to create an HashTable to populate with unique values and pass it back to another array and return it. The problem is in containsValue method, which always returns false, so all points are added in the HashTable.

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;
}

I really appreciate ay help.

Upvotes: 0

Views: 192

Answers (2)

Antonio Iacobucci
Antonio Iacobucci

Reputation: 59

Solved

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;
}

Wrapper

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;
    }
}

Upvotes: 0

Yoav Gur
Yoav Gur

Reputation: 1386

h.containsValue(pt) compares the addresses of the arrays, not their contents, when looking for a match.

To achieve what you want, you can write a wrapper class to be used as values in the map, and override equals and hashcode for it.

Upvotes: 2

Related Questions