Java 如果有基于int的equals/hashcode,那么';这是匹配a的最佳方式;全称;来自另一个集合的对象?

Java 如果有基于int的equals/hashcode,那么';这是匹配a的最佳方式;全称;来自另一个集合的对象?,java,collections,big-o,Java,Collections,Big O,假设你上过这个DTO课: public class MyObj{ private int id; private String displayName; private String backendData; public boolean equals(Object obj){ return id.equals(obj); } private int hashCode(){ return id.hashCode(); } } 假设一个用户从一个只显示displayN

假设你上过这个DTO课:

public class MyObj{
 private int id;

 private String displayName;
 private String backendData;

 public boolean equals(Object obj){
  return id.equals(obj);
 }

 private int hashCode(){
  return id.hashCode();
 }
}
假设一个用户从一个只显示displayName和id#在后台关联的列表中选择了几个MyObj实例。为了节省带宽,您不发送后端数据。当他们将所选内容提交给您时,客户只会向您发送id

现在,您已经在集合中维护了服务器端的原始选项列表。从集合中获取“full”对象的简单方法是遍历集合并对每个对象调用“.equals()”。这以O(n)表示,但:(

对于像HashSet这样的常量时间操作集合,如果我知道对象的标识,我应该能够在常量时间中检索对象。但是HashSet只有一个“contains()”方法,并且不返回它找到的对象


有什么建议吗?一如既往,谢谢大家!我想整个系列的id都是唯一的


几乎可以使用
Map
然后使用
Map。get(id)
是渐近常数时间。

您的对象不起作用(因为您不能对基本数据类型调用方法)。将
id
更改为整数,并在散列集合中使用它

Map<Integer, T> objectMap = ...;
Integer id = someidfromfrontend;
T anObj = objectMap.get(id);
Map objectMap=。。。;
整数id=someidfromfrontend;
T anObj=objectMap.get(id);

您的问题提出了多个问题IMHO:首先,不要将db id用作哈希键,如果它是自动生成的,您可能会遇到麻烦。第二,hashset/map使用hashcode和equals方法来检索对象(当您使用getmethod时)。首先,哈希代码用于快速找到对象可能所在的存储桶。然后,如果哈希集合中存在冲突,并且该存储桶中存在多个对象,则将使用equals来检索该对象。因此,当您在类的实例中使用get时,仅需要哈希代码中使用的字段和equals获取正确的值以检索对象。在这种情况下,如果您的对象具有正确的id(但其他字段错误)它可用于检索填充了otherfield的对应字段。该字段或u可使用映射。

哈希代码仅用于获取对象的快速数字。equals应对要验证对象相等性的所有字段进行完整比较

public class MyObj
{
    private final Integer id;

    private String displayName;
    private String backendData;

    public boolean equals(Object obj)
    {
        final MyObj other;

        if(obj == null || obj.getClass() != MyObj.class)
        {
            return (false);
        }

        other = (MyObj)obj;

        if(!(displayName.equals(other.displayName))
        {
            return (false);
        }

        if(!(backendData.equals(other.backendData))
        {
            return (false);
        }

        return (true);
    }

    private int hashCode()
    {
        return id.hashCode();
    }
}

这假设所有字段都不能为空,如果它们可以为空,则在if语句中要复杂一些。

(a)使用ID作为散列键会遇到什么样的问题?我不知道有什么问题。(b)
HashSet
没有
get
方法。a.如果你不相信我的话,可以在hibernate网站上查找它。B.我在回答关于如何使用hash检索类似于哈希表的集合的元素的部分,因为在我看来,这方面有一些不明确的地方。我的解释不正确吗?(a)我必须说,我不太相信我在Hibernate网站上读到的内容!(b)你对哈希表工作原理的解释是非常正确的。但是,由于
HashSet
没有
get
方法,这些事实无助于解决问题。你可以用“那或者你可以使用一个映射”作为结论-这是绝对正确的,但并不需要对哈希表进行解释!答:问题不在于你是否同意hibernate站点的说法,事实是,如果你有一些orm框架,并将你的bean配置为自动生成id(或者,如果出于某种原因,orm使用内部序列器生成持久化bean“id”)然后,在hashcode/equals中使用该id字段将使这些方法产生不可预测的行为,有时甚至是完全错误的行为。b.我所说的这些事实是为了阐明散列集合如何工作的问题,而java的Set接口没有get方法这一事实在这里没有得到解决不,如果你对引起麻烦的事情提出索赔,你有责任予以支持。只需说“查找”不是备份。您刚才给出的问题描述是备份-谢谢。但是,很明显,问题只存在于对象创建后生成的ID上;OP的代码可能不会这样做(DTO通常不会这样做)。(b)我注意到Set没有get方法这一事实没有得到解决;这就是为什么我评论指出这一点。这是一个使哈希集无法按照您描述的方式使用的问题。您是对的,但这是stackoverflow,不是IDE。我本可以使用Integer。我讨厌在已经有了Integer的情况下创建额外的数据结构y集合,但我认为你是正确的。你可以使用,但它不会像地图上的a一样快。这是一个宽泛的说法,只是部分正确,因为它在很大程度上取决于你的业务场景。如果你向集合中添加项目,并更改了业务密钥(displayName)若要保持唯一性,您的equals方法将导致问题。不可变对象是一件美妙的事情:-)如果您没有可以更改的状态,那么这些问题就不会出现。此外,如果状态更改,我希望哈希代码也会更改,这意味着您不应该将计划更改的对象放入集合中。