为什么Set不提供获取与另一个元素相等的元素的操作?

Set<Foo> set = ...;
...
Foo foo = new Foo(1, 2, 3);
Foo bar = set.get(foo);   // get the Foo element from the Set that equals foo

我可以问Set是否包含一个等于bar的元素,那么为什么我不能得到那个元素呢?:(

为了澄清,equals方法被重写,但它只检查其中一个字段,而不是所有字段。两个相等的Foo对象可以有不同的值,这就是为什么我不能只用Foo。


当前回答

你可以使用Iterator类

import java.util.Iterator;
import java.util.HashSet;

public class MyClass {
 public static void main(String[ ] args) {
 HashSet<String> animals = new HashSet<String>();
animals.add("fox");
animals.add("cat");
animals.add("dog");
animals.add("rabbit");

Iterator<String> it = animals.iterator();
while(it.hasNext()) {
  String value = it.next();
  System.out.println(value);   
 }
 }
}

其他回答

快速帮助方法,可以解决这种情况:

<T> T onlyItem(Collection<T> items) {
    if (items.size() != 1)
        throw new IllegalArgumentException("Collection must have single item; instead it has " + items.size());

    return items.iterator().next();
}

哈希码的契约清楚地表明:

如果根据Object方法,两个对象是相等的,那么在这两个对象上调用hashCode方法必须产生相同的整数结果。

所以你的假设是

为了澄清,equals方法被重写,但它只检查其中之一 田地,不是全部。所以两个相等的Foo对象可以 有不同的值,这就是为什么我不能只使用foo。”

是错误的,你违反了合同。如果我们看Set接口的"contains"方法,我们有:

boolean contains(Object o); 如果此集合包含指定的元素,则返回true。更多的 形式上,当且仅当此集合包含元素时返回true "e"使得o==null ?E ==null: o. = (E)

为了实现您想要的效果,您可以使用Map,在其中定义键并使用定义对象如何彼此不同或相等的键存储元素。

如果你想要HashSet中的第n个元素,你可以使用下面的解决方案, 这里我在HashSet中添加了ModelClass对象。

ModelClass m1 = null;
int nth=scanner.nextInt();
for(int index=0;index<hashset1.size();index++){
    m1 = (ModelClass) itr.next();
    if(nth == index) {
        System.out.println(m1);
        break;
    }
}

使用Java 8,你可以做到:

Foo foo = set.stream().filter(item->item.equals(theItemYouAreLookingFor)).findFirst().get();

但是要小心,.get()会抛出一个NoSuchElementException,或者你可以操作一个Optional项。

如果元素是相等的,那么获取它就没有意义了。Map更适合这个用例。


如果你仍然想找到元素,你没有其他选择,只能使用迭代器:

public static void main(String[] args) {

    Set<Foo> set = new HashSet<Foo>();
    set.add(new Foo("Hello"));

    for (Iterator<Foo> it = set.iterator(); it.hasNext(); ) {
        Foo f = it.next();
        if (f.equals(new Foo("Hello")))
            System.out.println("foo found");
    }
}

static class Foo {
    String string;
    Foo(String string) {
        this.string = string;
    }
    @Override
    public int hashCode() { 
        return string.hashCode(); 
    }
    @Override
    public boolean equals(Object obj) {
        return string.equals(((Foo) obj).string);
    }
}