如何从java.util.Set获取第一项?

时间:2013-12-11 05:22:16

标签: java set

我有一个设置实例:

Set<String> siteIdSet = (Set<String>) pContext.getParent().getPropertyValue(getCatalogProperties().getSitesPropertyName());

pContext.getParent().getPropertyValue()是开箱即用的代码,我无需修改任何控件。

要求:

我想从中获取第一个默认元素(总是)。但是,我找不到get(index)中的方法ArrayList

因此,现在,我这样做。

for (Iterator<String> it = siteIdSet.iterator(); it.hasNext();) {
    siteId = it.next();
    break;
}

是否有任何(其他)有效方式(简短且更好)实现此目标?

14 个答案:

答案 0 :(得分:73)

这将返回第一个元素

set.iterator().next();

答案 1 :(得分:26)

来自Oracle docs

  

正如其名称所暗示的,此界面模拟了数学抽象。

Set Theory中,“a”set“是不同对象的集合,本身被视为一个对象。” - [Wikipedia - Set]

数学上,集合中的元素不是个性化的。他们唯一的身份来自他们在集合中的存在。因此,在集合中获取“第一”元素是没有意义的,因为从概念上讲这样的任务是不合逻辑的。

从集合中获取“first”元素可能没有意义,但如果您只需要从集合中获取单个对象(无法保证哪个对象),则可以执行以下操作:

for(String aSiteId: siteIdSet) {
    siteId = aSiteId;
    break;
}

这是一个稍微短一些的方式(比你发布的方法)获得Set的“第一个”对象,但是由于Iterator仍然被创建(在引擎盖下)它不会授予任何性能益处。

答案 2 :(得分:21)

或者,使用Java8:

Object firstElement = set.stream().findFirst().get();

然后你可以马上做点什么:

set.stream().findFirst().ifPresent(<doStuffHere>);

或者,如果您想在缺少元素的情况下提供替代方法(我的示例返回新的默认字符串):

set.stream().findFirst().orElse("Empty string");

如果缺少第一个元素,您甚至可以抛出异常:

set.stream().findFirst().orElseThrow(() -> new MyElementMissingException("Ah, blip, nothing here!"));

感谢Alex Vulaj提示我除了最初抓住第一个元素之外还提供更多示例。

答案 3 :(得分:8)

Set是一个独特的项目集合。所以没有第一个元素的概念。如果您希望按排序顺序排列项目,则可以使用TreeSet从中TreeSet#first()检索第一个元素。

答案 4 :(得分:6)

TL;博士

致电TreeSet::first

移动元素,然后调用first()

new TreeSet<String>( 
    pContext.getParent().getPropertyValue( … )   // Transfer elements from your `Set` to this new `TreeSet`, an implementation of the `SortedSet` interface. 
).first()

Set没有订单

正如其他人所说,根据定义,Set没有订单。因此,要求“第一”元素没有意义。

Set的某些实现具有诸如添加项目的顺序之类的顺序。可以通过Iterator获得非官方订单。但该命令是偶然的,不能保证。如果幸运的话,支持Set的实施可能确实是SortedSet

CAVEAT:如果订单很关键,不依赖此类行为。如果可靠性并不重要,那么这种无证件的行为可能会很方便。如果给出Set你没有其他可行的选择,那么尝试这可能比没有更好。

Object firstElement = mySet.iterator().next();

直接解决问题...不,在处理空集的可能情况时,不是从迭代器中获取第一个元素的任何更短的方法。不过,我希望if的{​​{1}}测试而不是问题的isEmpty循环。

for

使用if ( ! mySet.isEmpty() ) { Object firstElement = mySet.iterator().next(); )

如果您关心在SortedSet中维护排序顺序,请使用SortedSet实施。这些实现包括:

使用SortedSet For Insertion-Order

如果您只需按照添加到LinkedHashSet的顺序记住元素,请使用LinkedHashSet

引用文档,这个类......

  

维护一个贯穿其所有条目的双向链表。此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。

答案 5 :(得分:3)

Set不会强制执行排序。无法保证您始终可以获得第一个&#34;即使你使用HashSet上的迭代器,就像你在问题中所做的那样。

如果您需要具有可预测的排序,则需要使用LinkedHashSet实现。迭代LinkedHashSet时,您将按照插入的顺序获取元素。您仍然需要使用迭代器,因为在get中使用LinkedHashSet方法需要您在任何地方使用具体类。

答案 6 :(得分:3)

正如您所说,pContext.getParent().getPropertyValue返回Set。您可以将Set转换为List以获取第一个元素。只需更改您的代码:

 Set<String> siteIdSet = (Set<String>) pContext.getParent().getPropertyValue(..);
 List<String> siteIdList=new ArrayList<>(siteIdSet);

 String firstItem=siteIdList.get(0);

答案 7 :(得分:2)

访问获取迭代器所需的元素。但是Iterator不保证特定的顺序,除非它是一些例外情况。所以它不确定得到第一个元素。

答案 8 :(得分:2)

这是我前几天遇到的一个难题。 java.util.LinkedHashSet维护其内容的链接列表(默认情况下添加 - 排序),但不提供任何访问者。其他结构类型将无法在add()remove()contains()上提供O(1)。

您可以使用LinkedHashSet并获取其iterator(),抓取一个元素并将其丢弃。如果你不经常关心速度或记忆,经常对很多不同的设置这样做,那可能是你的解决方案......但这对我来说似乎很浪费。另外,我还有一些额外的功能。

我最后编写了自己的类,称为RandomAccessLinkedHashSet,它同时维护一个哈希表,一个双向链表和一个与订单无关的数组。我写它是为了遵守SetDeque,尽管Deque的实现有点粗略,因为它将不会包含已经包含的push()个元素,对于它来说有点延伸接口的合同。维护第三个结构(数组)对于您正在进行的操作根本不是必需的,但它也允许以任何能够实际提供随机值的容量访问集合中的随机元素。

如果您有兴趣,我可以提供此来源。我还没有Serialized但它在运行时效果很好。

如果您无法保证以任何方式提供的Set类型,那么您必须坚持使用Iterator

答案 9 :(得分:2)

这有效:

Object firstElement = set.toArray()[0]; 

答案 10 :(得分:1)

我只是遇到了同样的问题,并在这里找到了您的问题...

这是我的解决方案:

Set<Integer> mySetOfIntegers = new HashSet<Integer>();
/* ... there's at least one integer in the set ... */

Integer iFirstItemInSet = new ArrayList<Integer>(mySetOfIntegers).get(0);

答案 11 :(得分:0)

从Set中检索第一个元素没有意义。如果您有这样的要求,请使用ArrayList而不是sets。集不允许重复。它们包含不同的元素。

答案 12 :(得分:0)

按定义设置不是有序的。

你可能使用错误的收藏。

答案 13 :(得分:0)

Vector具有一些方便的功能:

doAStripe()

但是我同意-这可能会产生意想不到的后果,因为不能保证下标集是有序的。