I have a Set instance:
我有一个Set实例:
Set<String> siteIdSet = (Set<String>) pContext.getParent().getPropertyValue(getCatalogProperties().getSitesPropertyName());
The pContext.getParent().getPropertyValue()
is out-of-the-box code upon which I don't have any control to modify.
pContext.getParent()。getPropertyValue()是开箱即用的代码,我没有任何控件可以修改。
Requirement:
I wanted to get the first default element out of it (always). However, I couldn't find a method get(index)
like in an ArrayList
.
我想从中获取第一个默认元素(总是)。但是,我找不到类似于ArrayList的get(index)方法。
Hence, right now, I am doing like this.
因此,现在,我这样做。
for (Iterator<String> it = siteIdSet.iterator(); it.hasNext();) {
siteId = it.next();
break;
}
Is there any (other) efficient way (short and better) of achieving this?
有没有(其他)有效的方法(简短和更好)实现这一目标?
12 个解决方案
#1
24
From the Oracle docs:
来自Oracle文档:
As implied by its name, this interface models the mathematical set abstraction.
正如其名称所暗示的,此接口模拟数学集抽象。
In Set Theory, "a "set" is a collection of distinct objects, considered as an object in its own right." - [Wikipedia - Set].
在集合理论中,“一个”集合是一个不同对象的集合,被视为一个独立的对象。“ - [* - 集]。
Mathematically, elements in sets are not individualised. Their only identity is derived from their presence in the set. Therefore, there is no point in getting the "first" element in a set, as conceptually such a task is illogical.
在数学上,集合中的元素不是个性化的。他们唯一的身份来自他们在集合中的存在。因此,在集合中获取“第一”元素是没有意义的,因为从概念上讲这样的任务是不合逻辑的。
There may be no point to getting the "first" element from a set, but if all you need is to get one single object from a set (with no guarantees as to which object that is) you can do the following:
从集合中获取“first”元素可能没有意义,但如果您只需要从集合中获取单个对象(不保证哪个对象是),则可以执行以下操作:
for(String aSiteId: siteIdSet) {
siteId = aSiteId;
break;
}
This is a slightly shorter way (than the method you posted) to get the "first" object of a Set
, however since an Iterator is still being created (under the hood) it does not grant any performance benefit.
这是一个稍微短一些的方法(比你发布的方法)来获取Set的“第一个”对象,但是由于Iterator仍在创建(在引擎盖下),它不会给予任何性能优势。
#2
63
This will return the first element
这将返回第一个元素
set.iterator().next();
#3
17
Or, using Java8:
或者,使用Java8:
Object firstElement = set.stream().findFirst().get();
And then you can do stuff with it straight away:
然后你可以马上做一些事情:
set.stream().findFirst().ifPresent(<doStuffHere>);
Or, if you want to provide an alternative in case the element is missing (my example returns new default string):
或者,如果您想在缺少元素的情况下提供替代方法(我的示例返回新的默认字符串):
set.stream().findFirst().orElse("Empty string");
You can even throw an exception if the first element is missing:
如果缺少第一个元素,您甚至可以抛出异常:
set.stream().findFirst().orElseThrow(() -> new MyElementMissingException("Ah, blip, nothing here!"));
Kudos to Alex Vulaj
for prompting me to provide more examples beyond the initial grabbing of the first element.
感谢Alex Vulaj提示我除了最初抓住第一个元素之外还提供更多示例。
#4
8
Set is a unique collection of items. So there is no notion of first element. If you want items in the sorted order, you can use TreeSet from which you can retrieve the first element using TreeSet#first().
Set是一个独特的项目集合。所以没有第一个元素的概念。如果您想要按排序顺序排列项目,可以使用TreeSet从中使用TreeSet #first()从中检索第一个元素。
#5
6
tl;dr
Call TreeSet::first
Move elements, and call 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
Has No Order
As others have said, a Set
by definition has no order. Therefore asking for the “first” element has no meaning.
正如其他人所说,按定义Set没有顺序。因此,要求“第一”元素没有意义。
Some implementations of Set
have an order such as the order in which items were added. That unofficial order may be available via the Iterator
. But that order is accidental and not guaranteed. If you are lucky, the implementation backing your Set
may indeed be a SortedSet
.
Set的某些实现具有诸如添加项的顺序之类的顺序。可以通过Iterator获得非官方订单。但是这个命令是偶然的,不能保证。如果幸运的话,支持你的Set的实现可能确实是一个SortedSet。
CAVEAT: If order is critical, do not rely on such behavior. If reliability is not critical, such undocumented behavior might be handy. If given a Set
you have no other viable alternative, so trying this may be better than nothing.
CAVEAT:如果订单很重要,请不要依赖此类行为。如果可靠性并不重要,那么这种无证件的行为可能会很方便。如果给出一个Set,你没有其他可行的选择,所以尝试这个可能比没有好。
Object firstElement = mySet.iterator().next();
To directly address the Question… No, not really any shorter way to get first element from iterator while handling the possible case of an empty Set. However, I would prefer an if
test for isEmpty
rather than the Question’s for
loop.
直接解决问题...不,在处理空集的可能情况时,实际上没有任何更简单的方法从迭代器获取第一个元素。但是,我更喜欢ifEmpty的if测试而不是Question的for循环。
if ( ! mySet.isEmpty() ) {
Object firstElement = mySet.iterator().next();
)
Use SortedSet
If you care about maintaining a sort order in a Set
, use a SortedSet
implementation. Such implementations include:
如果您关心在Set中维护排序顺序,请使用SortedSet实现。这些实现包括:
-
TreeSet
. -
ConcurrentSkipListSet
. - In Google Guava, the
SortedSetMultimap
class returns aSortedSet
from itsasMap
method.
在Google Guava中,SortedSetMultimap类从其asMap方法返回SortedSet。
Use LinkedHashSet
For Insertion-Order
If all you need is to remember elements in the order they were added to the Set
use a LinkedHashSet
.
如果您只需按顺序记住元素,则使用LinkedHashSet将它们添加到Set中。
To quote the doc, this class…
引用文档,这堂课......
maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).
维护一个贯穿其所有条目的双向链表。此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。
#6
3
Set
does not enforce ordering. There is no guarantee that you will always get the "first" element even if you use an iterator over a HashSet
like you have done in the question.
Set不强制执行排序。即使您在问题中使用了HashSet上的迭代器,也无法保证始终获得“first”元素。
If you need to have predictable ordering, you need to use the LinkedHashSet
implementation. When you iterate over a LinkedHashSet, you will get the elements in the order you inserted. You still need to use an iterator, because having a get
method in LinkedHashSet
would need you to use the concrete class everywhere.
如果需要具有可预测的排序,则需要使用LinkedHashSet实现。迭代LinkedHashSet时,您将按照插入的顺序获取元素。您仍然需要使用迭代器,因为在LinkedHashSet中使用get方法需要您在任何地方使用具体类。
#7
3
As, you mentioned pContext.getParent().getPropertyValue
return Set
. You can convert Set
to List
to get the first element. Just change your code like:
因为,你提到了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);
#8
2
To Access the element you need to get an iterator . But Iterator does not guarantee in a particular order unless it is some Exceptional case. so it is not sure to get the first Element.
要访问获取迭代器所需的元素。但是迭代器并不保证特定的顺序,除非它是一些例外情况。所以它不确定得到第一个元素。
#9
2
This is a difficult question I came up against the other day myself. java.util.LinkedHashSet
maintains a linked list of its contents (addition-ordered by default) but does not provide any accessors. Other structure types will fail to provide O(1) on add()
, remove()
, and contains()
.
这是我前几天遇到的一个难题。 java.util.LinkedHashSet维护其内容的链接列表(默认情况下是附加顺序),但不提供任何访问者。其他结构类型将无法在add(),remove()和contains()上提供O(1)。
You can use a LinkedHashSet
and get its iterator()
, grab one element, and discard it. If you don't care too much about speed or memory when doing this frequently to numerous different sets, that is probably your solution... but that seemed wasteful to me. Plus I had a little extra desired functionality.
您可以使用LinkedHashSet并获取其iterator(),获取一个元素并丢弃它。如果你不经常关心速度或记忆,经常对很多不同的设置这样做,这可能是你的解决方案......但这对我来说似乎很浪费。另外,我还有一些额外的功能。
I ended up writing my own class, dubbed RandomAccessLinkedHashSet
, which concurrently maintains a hashtable, a doubly linked list, and an order-irrelevant array. I wrote it to comply with both Set
and Deque
, though the Deque implementation is a little sketchy since it will fail to push()
elements it already contains, a little bit of a stretch for the interface's contract. Maintaining the third structure, the array, is not necessary at all for what you're doing, but it also allows access to a random element in the set in whatever capacity you can actually provide a random value.
我最后编写了自己的类,名为RandomAccessLinkedHashSet,它同时维护一个哈希表,一个双向链表和一个与顺序无关的数组。我写它是为了遵守Set和Deque,虽然Deque实现有点粗略,因为它将无法推送已经包含的push()元素,这对于接口的契约来说有点延伸。维护第三个结构(数组)对于你正在做的事情根本不是必需的,但它也允许以任何能够实际提供随机值的容量访问集合中的随机元素。
If you're interested I can provide this source. I haven't Serialized
it yet but it works great in runtime.
如果您有兴趣,我可以提供此来源。我还没有序列化它,但它在运行时运行良好。
If you cannot guarantee the type of Set
provided in any way, then you'll have to stick with the Iterator
thing.
如果你不能保证以任何方式提供Set的类型,那么你将不得不坚持Iterator的东西。
#10
2
This works:
Object firstElement = set.toArray()[0];
#11
0
There is no point in retrieving first element from a Set. If you have such kind of requirement use ArrayList instead of sets. Sets do not allow duplicates. They contain distinct elements.
从集合中检索第一个元素没有意义。如果您有这样的要求,请使用ArrayList而不是sets。集不允许重复。它们包含不同的元素。
#12
0
Set by definition is not ordered.
根据定义设置不是有序的。
You probably use wrong collection.
你可能使用了错误的收藏。
#1
24
From the Oracle docs:
来自Oracle文档:
As implied by its name, this interface models the mathematical set abstraction.
正如其名称所暗示的,此接口模拟数学集抽象。
In Set Theory, "a "set" is a collection of distinct objects, considered as an object in its own right." - [Wikipedia - Set].
在集合理论中,“一个”集合是一个不同对象的集合,被视为一个独立的对象。“ - [* - 集]。
Mathematically, elements in sets are not individualised. Their only identity is derived from their presence in the set. Therefore, there is no point in getting the "first" element in a set, as conceptually such a task is illogical.
在数学上,集合中的元素不是个性化的。他们唯一的身份来自他们在集合中的存在。因此,在集合中获取“第一”元素是没有意义的,因为从概念上讲这样的任务是不合逻辑的。
There may be no point to getting the "first" element from a set, but if all you need is to get one single object from a set (with no guarantees as to which object that is) you can do the following:
从集合中获取“first”元素可能没有意义,但如果您只需要从集合中获取单个对象(不保证哪个对象是),则可以执行以下操作:
for(String aSiteId: siteIdSet) {
siteId = aSiteId;
break;
}
This is a slightly shorter way (than the method you posted) to get the "first" object of a Set
, however since an Iterator is still being created (under the hood) it does not grant any performance benefit.
这是一个稍微短一些的方法(比你发布的方法)来获取Set的“第一个”对象,但是由于Iterator仍在创建(在引擎盖下),它不会给予任何性能优势。
#2
63
This will return the first element
这将返回第一个元素
set.iterator().next();
#3
17
Or, using Java8:
或者,使用Java8:
Object firstElement = set.stream().findFirst().get();
And then you can do stuff with it straight away:
然后你可以马上做一些事情:
set.stream().findFirst().ifPresent(<doStuffHere>);
Or, if you want to provide an alternative in case the element is missing (my example returns new default string):
或者,如果您想在缺少元素的情况下提供替代方法(我的示例返回新的默认字符串):
set.stream().findFirst().orElse("Empty string");
You can even throw an exception if the first element is missing:
如果缺少第一个元素,您甚至可以抛出异常:
set.stream().findFirst().orElseThrow(() -> new MyElementMissingException("Ah, blip, nothing here!"));
Kudos to Alex Vulaj
for prompting me to provide more examples beyond the initial grabbing of the first element.
感谢Alex Vulaj提示我除了最初抓住第一个元素之外还提供更多示例。
#4
8
Set is a unique collection of items. So there is no notion of first element. If you want items in the sorted order, you can use TreeSet from which you can retrieve the first element using TreeSet#first().
Set是一个独特的项目集合。所以没有第一个元素的概念。如果您想要按排序顺序排列项目,可以使用TreeSet从中使用TreeSet #first()从中检索第一个元素。
#5
6
tl;dr
Call TreeSet::first
Move elements, and call 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
Has No Order
As others have said, a Set
by definition has no order. Therefore asking for the “first” element has no meaning.
正如其他人所说,按定义Set没有顺序。因此,要求“第一”元素没有意义。
Some implementations of Set
have an order such as the order in which items were added. That unofficial order may be available via the Iterator
. But that order is accidental and not guaranteed. If you are lucky, the implementation backing your Set
may indeed be a SortedSet
.
Set的某些实现具有诸如添加项的顺序之类的顺序。可以通过Iterator获得非官方订单。但是这个命令是偶然的,不能保证。如果幸运的话,支持你的Set的实现可能确实是一个SortedSet。
CAVEAT: If order is critical, do not rely on such behavior. If reliability is not critical, such undocumented behavior might be handy. If given a Set
you have no other viable alternative, so trying this may be better than nothing.
CAVEAT:如果订单很重要,请不要依赖此类行为。如果可靠性并不重要,那么这种无证件的行为可能会很方便。如果给出一个Set,你没有其他可行的选择,所以尝试这个可能比没有好。
Object firstElement = mySet.iterator().next();
To directly address the Question… No, not really any shorter way to get first element from iterator while handling the possible case of an empty Set. However, I would prefer an if
test for isEmpty
rather than the Question’s for
loop.
直接解决问题...不,在处理空集的可能情况时,实际上没有任何更简单的方法从迭代器获取第一个元素。但是,我更喜欢ifEmpty的if测试而不是Question的for循环。
if ( ! mySet.isEmpty() ) {
Object firstElement = mySet.iterator().next();
)
Use SortedSet
If you care about maintaining a sort order in a Set
, use a SortedSet
implementation. Such implementations include:
如果您关心在Set中维护排序顺序,请使用SortedSet实现。这些实现包括:
-
TreeSet
. -
ConcurrentSkipListSet
. - In Google Guava, the
SortedSetMultimap
class returns aSortedSet
from itsasMap
method.
在Google Guava中,SortedSetMultimap类从其asMap方法返回SortedSet。
Use LinkedHashSet
For Insertion-Order
If all you need is to remember elements in the order they were added to the Set
use a LinkedHashSet
.
如果您只需按顺序记住元素,则使用LinkedHashSet将它们添加到Set中。
To quote the doc, this class…
引用文档,这堂课......
maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).
维护一个贯穿其所有条目的双向链表。此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。
#6
3
Set
does not enforce ordering. There is no guarantee that you will always get the "first" element even if you use an iterator over a HashSet
like you have done in the question.
Set不强制执行排序。即使您在问题中使用了HashSet上的迭代器,也无法保证始终获得“first”元素。
If you need to have predictable ordering, you need to use the LinkedHashSet
implementation. When you iterate over a LinkedHashSet, you will get the elements in the order you inserted. You still need to use an iterator, because having a get
method in LinkedHashSet
would need you to use the concrete class everywhere.
如果需要具有可预测的排序,则需要使用LinkedHashSet实现。迭代LinkedHashSet时,您将按照插入的顺序获取元素。您仍然需要使用迭代器,因为在LinkedHashSet中使用get方法需要您在任何地方使用具体类。
#7
3
As, you mentioned pContext.getParent().getPropertyValue
return Set
. You can convert Set
to List
to get the first element. Just change your code like:
因为,你提到了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);
#8
2
To Access the element you need to get an iterator . But Iterator does not guarantee in a particular order unless it is some Exceptional case. so it is not sure to get the first Element.
要访问获取迭代器所需的元素。但是迭代器并不保证特定的顺序,除非它是一些例外情况。所以它不确定得到第一个元素。
#9
2
This is a difficult question I came up against the other day myself. java.util.LinkedHashSet
maintains a linked list of its contents (addition-ordered by default) but does not provide any accessors. Other structure types will fail to provide O(1) on add()
, remove()
, and contains()
.
这是我前几天遇到的一个难题。 java.util.LinkedHashSet维护其内容的链接列表(默认情况下是附加顺序),但不提供任何访问者。其他结构类型将无法在add(),remove()和contains()上提供O(1)。
You can use a LinkedHashSet
and get its iterator()
, grab one element, and discard it. If you don't care too much about speed or memory when doing this frequently to numerous different sets, that is probably your solution... but that seemed wasteful to me. Plus I had a little extra desired functionality.
您可以使用LinkedHashSet并获取其iterator(),获取一个元素并丢弃它。如果你不经常关心速度或记忆,经常对很多不同的设置这样做,这可能是你的解决方案......但这对我来说似乎很浪费。另外,我还有一些额外的功能。
I ended up writing my own class, dubbed RandomAccessLinkedHashSet
, which concurrently maintains a hashtable, a doubly linked list, and an order-irrelevant array. I wrote it to comply with both Set
and Deque
, though the Deque implementation is a little sketchy since it will fail to push()
elements it already contains, a little bit of a stretch for the interface's contract. Maintaining the third structure, the array, is not necessary at all for what you're doing, but it also allows access to a random element in the set in whatever capacity you can actually provide a random value.
我最后编写了自己的类,名为RandomAccessLinkedHashSet,它同时维护一个哈希表,一个双向链表和一个与顺序无关的数组。我写它是为了遵守Set和Deque,虽然Deque实现有点粗略,因为它将无法推送已经包含的push()元素,这对于接口的契约来说有点延伸。维护第三个结构(数组)对于你正在做的事情根本不是必需的,但它也允许以任何能够实际提供随机值的容量访问集合中的随机元素。
If you're interested I can provide this source. I haven't Serialized
it yet but it works great in runtime.
如果您有兴趣,我可以提供此来源。我还没有序列化它,但它在运行时运行良好。
If you cannot guarantee the type of Set
provided in any way, then you'll have to stick with the Iterator
thing.
如果你不能保证以任何方式提供Set的类型,那么你将不得不坚持Iterator的东西。
#10
2
This works:
Object firstElement = set.toArray()[0];
#11
0
There is no point in retrieving first element from a Set. If you have such kind of requirement use ArrayList instead of sets. Sets do not allow duplicates. They contain distinct elements.
从集合中检索第一个元素没有意义。如果您有这样的要求,请使用ArrayList而不是sets。集不允许重复。它们包含不同的元素。
#12
0
Set by definition is not ordered.
根据定义设置不是有序的。
You probably use wrong collection.
你可能使用了错误的收藏。