Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HashMap添加所有项目,即使重复_Java_Hashmap - Fatal编程技术网

Java HashMap添加所有项目,即使重复

Java HashMap添加所有项目,即使重复,java,hashmap,Java,Hashmap,我一直试图在没有任何运气的情况下列出模型中的所有点。当我执行此命令时 HashList<Point> points=new HashList<Point>(16); //add +y side points.add(new Point(-5.0,5.0,-5.0)); points.add(new Point(-5.0,5.0,5.0)); points.add(new Point(5.0,5.0,5.0)); poin

我一直试图在没有任何运气的情况下列出模型中的所有点。当我执行此命令时

    HashList<Point> points=new HashList<Point>(16);

    //add +y side
    points.add(new Point(-5.0,5.0,-5.0));
    points.add(new Point(-5.0,5.0,5.0));
    points.add(new Point(5.0,5.0,5.0));

    points.add(new Point(-5.0,5.0,-5.0));
    points.add(new Point(5.0,5.0,5.0));
    points.add(new Point(5.0,5.0,-5.0));

    //add -x side
    points.add(new Point(-5.0,5.0,-5.0));
    points.add(new Point(-5.0,-5.0,-5.0));
    points.add(new Point(-5.0,-5.0,5.0));

    points.add(new Point(-5.0,5.0,-5.0));
    points.add(new Point(-5.0,-5.0,5.0));
    points.add(new Point(-5.0,5.0,5.0));

    int length=points.length(); //equals 12, 6 expected

    Point a=new Point(-5.0,5.0,-5.0);
    Point b=new Point(-5.0,5.0,-5.0);
    int aHashCode=a.hashCode(); //-737148544
    int bHashCode=b.hashCode(); //-737148544
    boolean equals=a.equals(b); //true
在HashList中,由于某种原因永远不会执行。有什么想法吗

哈希列表:

package dataTypes;

import java.util.ArrayList;
import java.util.HashMap;

public class HashList<E> {
    private HashMap<E,Integer> map;
    private ArrayList<E> data;
    private int count=0;

    public HashList() {
        map=new HashMap<E,Integer>();
        data=new ArrayList<E>();
    }

    public HashList(int size) {
        map=new HashMap<E,Integer>(size);
        data=new ArrayList<E>(size);
    }

    public int add(E e) { //returns key
        if (map.containsKey(e)) {
            return map.get(e);
        } else {
            map.put(e, count);
            data.add(count,e);
            return count++;
        }
    }

    public int getKey(E e) {
        return map.get(e);
    }

    public E get(int key) {
        return data.get(key);
    }

    public int length() {
        return count;
    }
}

正如rolfl所注意到的,尝试使用java equals方法来比较具有可接受错误的点是没有用的(如果您有疑问,请参阅下面的TL/DR部分)

所以,你必须用艰难的方式去做。甚至不要想象使用
map.containsKey(e)
,而是在
HashList
中创建一个显式方法。我将从该界面开始:

public interface DistEquality<E> {
    boolean distEquals(E compare);
}
并以这种方式修改HashList

public class HashList<E  extends DistEquality<E>> {
    ...
    public int distValue(E e) {
        for (Entry<E, Integer> entry: map.entrySet()) {
            if (e.distEquals(entry.getKey())) {
                return entry.getValue();
            }
        }
        return -1;
    }

    public int add(E e) { //returns key
        int pos = distValue(e);
        if (pos != -1) {
            return pos;
        } else {
            map.put(e, count);
            data.add(count,e);
            return count++;
        }
    }
    ...
}
但是正如rolfl所注意到的,这是不够的,因为javadoc for
Object.hashCode()
声明如果根据equals(Object)方法两个对象相等,那么对这两个对象中的每一个调用hashCode方法必须产生相同的整数结果

很难想象一个与上述相等方法兼容的智能哈希。更糟糕的是,一旦一个点得到一个hashCode值,任何其他点都处于有限数量的
defaultError
,您可以想象一组完整的点,它们都是2/2相等的,因此hashCode应该是一个常量

更糟糕的是,由于要求equals是自反的、对称的和传递的,所以所有的点都应该是相等的


这样使用equal的想法似乎真的是一个不好的想法:-(

如果您希望哈希表能够包含重复项,那么哈希表实现是不正确的。在添加时,如果映射已经有键,您只需返回值…,这样您的重复项就永远不会被插入

若你们得到的是重复的,那个就意味着你们点的Equals/HashCode很可能搞糟了


现在,你的HashList实际上不允许重复,所以你最好去掉它,使用java集合中的HashSet。另外,获得一个像样的java IDE,比如netbeans、eclipse、IntellIJ,让它为你的point类生成equals/hashcode。

问题在于
equals(Object)中的
最后
。它总是返回
false
,即使您从
try
块返回
true

你会因此感到困惑:

boolean equals=a.equals(b); //true
…但这不是调用相同的
equals
方法-它调用
equals(Point)

您的
equals(Object)
方法应写成:

@Override public boolean equals(Object compare) {
    if (compare == this) {
        return true;
    }
    if (compare == null || compare.getClass() != getClass()) {
        return false;
    }
    Point temp = (Point) compare; // Guaranteed to work now
    return temp.x == x && temp.y == y && temp.z == z;
}
请注意:

  • 正如其他地方所指出的,你不能想出一个处理容差的等式/哈希……如果你用这些点做任何重要的算术运算,你就不可能再有精确的等式了
  • 你的类有公共字段,这通常是个坏主意
  • 您的类是可变的,从使用哈希代码的代码的角度来看,这是一个坏主意-当元素类型不可变时,集合更易于正确使用
  • 如果将类设置为final,则可以使用
    instanceof
    而不是
    getClass()
    复选框,这将有助于防止有人引入可变的子类(继承层次结构中的相等关系通常都很痛苦)

为什么不使用
集合
?除此之外,在
equals
方法中使用
try/finally
是很可怕的。请使用
instanceof
来代替。接下来,请提供一个简短但完整的程序来演示问题。我们不应该开始添加代码来创建相等点等。(请注意,
Point
中的几乎所有代码都与问题无关,因为您没有旋转任何点等。)这不会起作用!hashCode()方法使用双对象的hashCode(),即(即使值相等,对于每个双对象几乎都是唯一的。equals方法也存在同样的问题,在这里比较对象实例,而不是值。使用双原语而不是对象。您需要比较像“if(Math.abs(a-b)<0.00001)”这样的值)'那么它们是相等的。我不知道如何从哈希值为int的double中构造哈希值。我建议使用使用使用equals方法的'TreeSet'或自定义comarator为什么不使用try来处理包含一些重复元素的较小数据子集并调试hashCode/equals方法?很可能您需要twea这只是部分答案。在不修改哈希代码的情况下修改equals将不起作用help@rolfl:您是对的,但即使equals方法也不尊重JDK契约-请参阅我的editI我对java是新手,但此修改是否会导致该类无法处理其他对象类型?该类是泛型的,应该是usab所有对象类型上的le。在这个特定实例中,我要查找的点与它们从同一个点集中产生的点完全相同(例如,立方体只有8个点,但需要36个点才能将其建模为三角形)一旦进入软件,所有点都应该以完全相同的方式进行操作,以便它们都应该继续具有完全相同的值,而不是近似值。这并不能回答为什么精确的双精度值仍然会导致重复。@MatthewCornelisse:Jon中给出了精确的双精度值仍然会导致重复的原因Skeet的回答。当您在类
Point
中定义几乎相等的方法时,我试图想象如何使用它。修改后的类将适用于实现
distEquals
方法的任何其他类。这意味着您可能需要包装现有类来实现它,或者更改逻辑并使用
AlmostEquals比较器
类,如
compare
可以使用
Comparable
类或
Comparator
。我不想得到重复项。问题是我得到了重复项,所以我在使用Eclipse如果你不想要重复项,那么你为什么不使用jus
public class HashList<E  extends DistEquality<E>> {
    ...
    public int distValue(E e) {
        for (Entry<E, Integer> entry: map.entrySet()) {
            if (e.distEquals(entry.getKey())) {
                return entry.getValue();
            }
        }
        return -1;
    }

    public int add(E e) { //returns key
        int pos = distValue(e);
        if (pos != -1) {
            return pos;
        } else {
            map.put(e, count);
            data.add(count,e);
            return count++;
        }
    }
    ...
}
public boolean equals(Object compare) {
    return ((compare instanceof Point) ? equals(compare, defaultError) : false);
}
boolean equals=a.equals(b); //true
@Override public boolean equals(Object compare) {
    if (compare == this) {
        return true;
    }
    if (compare == null || compare.getClass() != getClass()) {
        return false;
    }
    Point temp = (Point) compare; // Guaranteed to work now
    return temp.x == x && temp.y == y && temp.z == z;
}