为什么java.util.Set不能返回任何值?

时间:2012-03-06 11:47:10

标签: java set

java.util.Set仅指定返回所有记录的方法(通过Iterator或数组)。

为什么没有选项从Set返回任何值?

在现实生活中有很多意义。例如,我有一碗草莓,我想只拿一个。我完全不在乎哪一个。

为什么我不能在java中做同样的事情?

7 个答案:

答案 0 :(得分:5)

这不是负责任的。您必须询问Java集合框架的原始设计者。

一个可能的原因是具有非确定性行为的方法往往存在问题:

  • 他们使单元测试更难。
  • 他们让bug更难追查。
  • 他们更容易被那些没有阅读API文档的程序员误解和误用。

对于基于散列表的集合组织,“获取某个元素”方法的行为将是非确定性的,或者至少难以来确定/预测。

顺便说一下,您可以按如下方式轻松获取非空集的某些元素:

Object someObject = someSet.iterator().next();

获取真正的(伪)随机元素有点棘手/昂贵,因为您无法索引集合的元素。 (您需要将所有设置元素提取到数组中......)


在重新审视这一点时,我意识到还有另一个原因。简单地说Set基于集合的数学概念,并且数学集合中的元素没有顺序。谈论数学集的第一个元素毫无意义。

答案 1 :(得分:1)

java.util.Set是无序集合;你可以把它看作一个包含东西的包,但不是以任何特定的顺序。拥有get(int index)方法是没有意义的,因为集合中的元素没有索引。

标准Java库的设计者没有包含从Set获取随机元素的方法。如果你想知道为什么,这是你只能推测的东西。也许他们认为没有必要,或者他们甚至没想过。

自己编写一个方法很容易从Set中获取随机元素。

答案 2 :(得分:1)

如果您不关心元素的索引,请尝试使用Queue而不是Set。

    Queue q = new ArrayDeque();
    q.element(); // retrieves the first object but doesn't remove
    q.poll(); // retrieves and removes first object

答案 3 :(得分:1)

虽然普通的Set没有特别之处,但SortedSet和NavigableSet提供了有保证的顺序和支持它的方法。您可以使用first()last()

SortedSet<E> set = ...
E e1 = set.first(); // a value
E e2 = set.last(); // also a value.

答案 4 :(得分:0)

实际上迭代器比使用get(position)要好得多(这是你可以在java.util.List上做的事情)。它允许在迭代期间对一件事进行集合修改。你没有将它们装入套装的原因可能是因为它们中的大多数都不能保证插入顺序。您可以随时执行new ArrayList<?>(mySet).get(position)

之类的操作

答案 5 :(得分:0)

如果您不关心性能,可以创建新类型并将数据备份到arraylist中。

(请注意,在弃权之前,这只是一个天真的想法,而不是建议的最终解决方案)

import ...

public class PickableSet<E> extends AbstractSet<E>{

    private final List<E> arrayList = new ArrayList<E>();
    private final Set<E>  hashSet   = new HashSet<E>();
    private final Random  random    = new Random();

    public boolean add( E e ) {
        return hashSet.add( e ) && arrayList.add( e );
    }
    public int size() {
        return arrayList.size();
    }
    public Iterator<E> iterator() {
        return hashSet.iterator();
    }

    public E pickOne() {
        return arrayList.get( random.nextInt( arrayList.size() ) );
    }
}

当然,由于您使用的是不同的界面,因此必须进行强制转换以调用该方法:

Set<String> set = new PickableSet<String>();
set.add("one");
set.add("other");
String oneOfThem = ((PickableSet)set).pickOne();

https://gist.github.com/1986763

答案 6 :(得分:-1)

嗯,你可以像这样做一些工作

    Set<String> s = new HashSet<String>();
    Random r = new Random();
    String res = s.toArray(new String[0])[r.nextInt(s.toArray().length)];

这会从集合中抓取随机选择的对象。