59

希望有人能解释为什么我不能从HashSet.

考虑我HashSet包含正确覆盖MyHashObjects他们的hashCode()和方法的列表。equals()

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

那么为什么没有get()类似于contains()工作原理的方法呢?

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

4

10 回答 10

49

如果您知道要检索的元素,那么您已经拥有该元素。Set给定一个元素,a 唯一要回答的问题是它是否contains()存在。

如果要对元素进行迭代,只需使用Set.iterator().

听起来你想要做的是为元素的等价类指定一个规范元素。您可以使用 aMap<MyObject,MyObject>来执行此操作。请参阅this SO questionthis one进行讨论。

如果您真的确定要找到一个元素,该.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;
}

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

于 2012-08-18T00:09:49.570 回答
11

你可以HashMap<MyHashObject,MyHashObject>代替HashSet<MyHashObject>.

调用ContainsKey()你的“重建”MyHashObject将首先hashCode()检查集合,如果重复的哈希码被击中,最后equals()检查你的“重建”与原始,在此你可以使用检索原始get()

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

于 2015-06-05T07:52:51.913 回答
7

听起来您实际上是在尝试将哈希码用作映射中的键(这是 HashSets 在幕后所做的)。你可以明确地做到这一点,通过声明HashMap<Integer, MyHashObject>.

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

于 2012-08-18T00:11:08.807 回答
6

如果您知道Set中元素的顺序,则可以通过将Set转换为Array来检索它们。像这样的东西:

Set mySet = MyStorageObject.getMyStringSet();
Object[] myArr = mySet.toArray();
String value1 = myArr[0].toString();
String value2 = myArr[1].toString();
于 2015-02-11T22:08:49.907 回答
3

您需要获取对包含在 Set 对象中的对象的引用的想法很常见。它可以通过2种方式存档:

  1. 根据需要使用 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;
    }
    

要使这种方法起作用,您需要同时覆盖 hashCode() 和 equals(Object o) 方法在最坏的情况下,我们有 O(n)

  1. 第二种方法是使用 TreeSet

    public Object getObjectReference(TreeSet<Xobject> set, Xobject obj) {
        if (set.contains(obj)) {
            return set.floor(obj);
        }
        return null;
    }
    

这种方法使 O(log(n)) 更有效。对于这种方法,您不需要覆盖 hashCode,但您必须实现 Comparable 接口。(定义函数 compareTo(Object o))。

于 2016-08-27T19:11:13.053 回答
1

如果我在我的应用程序中确定该对象没有用于任何列表或哈希数据结构中的搜索,并且没有在其他地方使用 equals 方法,除了在添加时间接用于哈希数据结构的方法。是否建议在 equals 方法中更新集合中的现有对象。请参考以下代码。如果我将这个 bean 添加到 HashSet,我可以对键(id)上的匹配对象进行组聚合。通过这种方式,我也可以实现 sum、max、min 等聚合函数。如果不建议,请随时与我分享您的想法。

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;
    }
}
于 2015-07-22T03:31:10.623 回答
1

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

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());
}
于 2018-02-04T06:26:38.467 回答
1

最简单的方法之一是转换为数组:

for(int i = 0; i < set.size(); i++) {
    System.out.println(set.toArray()[i]);
}
于 2019-09-13T12:20:20.553 回答
0

如果您可以List用作数据结构来存储数据,而不是Map将结果存储在 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;

它基本上是重新实现Set可以访问和更改哪些项目。

于 2016-03-06T23:08:34.657 回答
0

set.stream().findFirst() 呢?

于 2022-02-01T06:10:03.287 回答