Java:从哈希集中检索元素

Java:从哈希集中检索元素,java,Java,希望有人能解释为什么我无法从哈希集检索元素 考虑我的HashSet包含一个MyHashObjects列表,它们的hashCode()和equals()方法被正确覆盖 我希望自己构造一个MyHashObject,并将相关的hash代码属性设置为某些值。 我可以使用contains()方法查询HashSet以查看集合中是否存在“等效”对象。 因此,即使contains()为这两个对象返回true,它们也可能不是=true 为什么没有类似于contains()的get()方法 有兴趣了解此API决策背

希望有人能解释为什么我无法从
哈希集
检索元素

考虑我的
HashSet
包含一个
MyHashObjects
列表,它们的
hashCode()
equals()
方法被正确覆盖

我希望自己构造一个
MyHashObject
,并将相关的hash代码属性设置为某些值。 我可以使用
contains()
方法查询
HashSet
以查看集合中是否存在“等效”对象。 因此,即使
contains()
为这两个对象返回true,它们也可能不是
=
true

为什么没有类似于
contains()
get()
方法


有兴趣了解此API决策背后的思想

如果您知道要检索的元素,那么您已经拥有了该元素。给定元素,
集合
要回答的唯一问题是它是否包含()

如果要对元素进行迭代,只需使用

听起来,您试图做的是为元素的等价类指定一个规范元素。您可以使用
映射来执行此操作。请参阅或进行讨论

如果您真的决定要找到一个元素,该元素
.equals()
必须使用
HashSet
约束您的原始元素,那么我认为您必须迭代它并自己检查
equals()
。API不允许您通过其哈希代码获取某些内容。所以你可以做:

MyObject findIfPresent(MyObject source, HashSet<MyObject> set)
{
   if (set.contains(source)) {
      for (MyObject obj : set) {
        if (obj.equals(source)) 
          return obj;
      } 
   }

  return null;
}
MyObject findIfPresent(MyObject源,HashSet)
{
if(集合包含(源)){
用于(MyObject对象:集合){
如果(对象等于(源))
返回obj;
} 
}
返回null;
}

蛮力和O(n)丑陋,但如果这是您需要做的…

听起来您实际上是在尝试将哈希代码用作映射中的键(这是哈希集在幕后所做的)。您可以通过声明
HashMap
显式地完成它


hashset没有
get
,因为通常作为参数提供给
get
方法的对象与返回的对象相同。

如果知道集合中元素的顺序,可以通过将集合转换为数组来检索它们。大概是这样的:

Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();
您可以使用
HashMap
代替
HashSet

在“重建的”
MyHashObject
上调用
ContainsKey()
首先将
hashCode()
-检查集合,如果找到重复的hashCode,最后将
equals()
-对照原始文件检查“重建的”文件,此时可以使用
get()


这是O(1),但缺点是您可能必须同时重写
equals()
hashCode()
方法。

如果我在我的应用程序中确信该对象未用于任何列表或哈希数据结构中的搜索,也未在其他地方使用equals方法,除了添加时在哈希数据结构中间接使用的方法。建议在“设置为等于”方法中更新现有对象。请参阅以下代码。如果我将thisbean添加到HashSet,我可以在key(id)上的匹配对象上进行组聚合。通过这种方式,我能够实现聚合功能,如总和,最大值,最小值。。。也如果不可取,请随时与我分享您的想法

public class MyBean {

    String id,
           name;
    double amountSpent;

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if(obj!=null && obj instanceof MyBean ) {
            MyBean tmpObj = (MyBean) obj;
            if(tmpObj.id!=null && tmpObj.id.equals(this.id)) {
                tmpObj.amountSpent += this.amountSpent;
                return true;
            }
        }
        return false;
    }
}

如果可以使用
List
作为数据结构来存储数据,而不是使用
Map
将结果存储在映射的值中,则可以使用以下代码段并将结果存储在同一对象中

下面是一个节点类:

private class Node {
    public int row, col, distance;

    public Node(int row, int col, int distance) {
        this.row = row;
        this.col = col;
        this.distance = distance;
    }

    public boolean equals(Object o) {
        return (o instanceof Node &&
                row == ((Node) o).row &&
                col == ((Node) o).col);
    }
}
如果将结果存储在距离变量中,并且根据列表中的项目的坐标对其进行检查,则只要每个数据只需要存储一个元素,就可以通过lastIndexOf方法使用以下方法将距离更改为新的距离:

    List<Node> nodeList;
    nodeList = new ArrayList<>(Arrays.asList(new Node(1, 2, 1), new Node(3, 4, 5)));
    Node tempNode = new Node(1, 2, 10);
    if(nodeList.contains(tempNode))
        nodeList.get(nodeList.lastIndexOf(tempNode)).distance += tempNode.distance;
列出节点列表;
nodeList=newarraylist(Arrays.asList(新节点(1,2,1),新节点(3,4,5));
节点tempNode=新节点(1,2,10);
if(nodeList.contains(tempNode))
nodeList.get(nodeList.lastIndexOf(tempNode)).distance+=tempNode.distance;

它基本上是重新实现集合
,其项目可以访问和更改。

通常需要获取集合对象中包含的对象的引用。它可以通过两种方式存档:

  • 根据需要使用HashSet,然后:

    public Object getObjectReference(HashSet<Xobject> set, Xobject obj) {
        if (set.contains(obj)) {
            for (Xobject o : set) {
                if (obj.equals(o))
                    return o;
            }
        }
        return null;
    }
    
    公共对象getObjectReference(HashSet集,Xobject obj){ if(集合包含(obj)){ 用于(Xobject o:set){ 如果(对象等于(o)) 返回o; } } 返回null; }
  • 要使这种方法起作用,您需要重写hashCode()和equals(Object o)方法 在最坏的情况下,我们有O(n)

  • 第二种方法是使用TreeSet

    public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) {
        if (set.contains(obj)) {
            return set.floor(obj);
        }
        return null;
    }
    
    public Object getObjectReference(树集,Xobject obj){
    if(集合包含(obj)){
    返回装置。地板(obj);
    }
    返回null;
    }
    
  • 这种方法使O(log(n))更有效。
    这种方法不需要重写hashCode,但必须实现类似的接口。(定义函数compareTo(对象o))。

    首先将集合转换为数组。 然后,通过数组的索引获取项

    Set uniqueItem = new HashSet() ;
    uniqueItem.add("0");
    uniqueItem.add("1");
    uniqueItem.add("0");
    
    Object[] arrayItem = uniqueItem.toArray(); 
    for(int i = 0; i < uniqueItem.size();i++){
        System.out.println("Item "+i+" "+arrayItem[i].toString());
    }
    
    Set uniqueItem=new HashSet();
    唯一项目。添加(“0”);
    唯一项目。添加(“1”);
    唯一项目。添加(“0”);
    Object[]arrayItem=uniqueItem.toArray();
    对于(int i=0;i
    最简单的方法之一是转换为数组:

    for(int i = 0; i < set.size(); i++) {
        System.out.println(set.toArray()[i]);
    }
    
    for(int i=0;i