为什么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。


当前回答

如果你有一个相等的对象,为什么你需要集合中的一个?如果它仅与键“相等”,则Map将是更好的选择。

不管怎样,下面的方法就可以了:

Foo getEqual(Foo sample, Set<Foo> all) {
  for (Foo one : all) {
    if (one.equals(sample)) {
      return one;
    }
  } 
  return null;
}

在Java 8中,这可以变成一行代码:

return all.stream().filter(sample::equals).findAny().orElse(null);

其他回答

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

<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();
}

如果你的set实际上是一个NavigableSet<Foo>(例如TreeSet),并且Foo实现Comparable<Foo>,你可以使用

Foo bar = set.floor(foo); // or .ceiling
if (foo.equals(bar)) {
    // use bar…
}

(感谢@eliran-malka的评论。)

尝试使用数组:

ObjectClass[] arrayName = SetOfObjects.toArray(new ObjectClass[setOfObjects.size()]);

使用Java 8,你可以做到:

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

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

如果你想要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;
    }
}