[java] How to get first item from a java.util.Set?

I have a Set instance:

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.

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.

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?

This question is related to java set

The answer is


As, you mentioned pContext.getParent().getPropertyValue return Set. You can convert Set to List to get the first element. Just change your code like:

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

 String firstItem=siteIdList.get(0);

tl;dr

Call SortedSet::first

Move elements, and call 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.

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.

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.

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.

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:

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.

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).


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.

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.


This will return the first element

set.iterator().next();

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.


Or, using 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.


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.


Set by definition is not ordered.

You probably use wrong collection.


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().

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.

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.

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.


I just had the same problem and found your question here ...

This was my solution:

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

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

This works:

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

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().


Vector has some handy features:

Vector<String> siteIdVector = new Vector<>(siteIdSet);
String first = siteIdVector.firstElement();
String last = siteIdVector.lastElement();

But I do agree - this may have unintended consequences, since the underling set is not guaranteed to be ordered.