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

JavaSet

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

This will return the first element

set.iterator().next();

Solution 2 - Java

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.

Solution 3 - Java

From the Oracle docs:

> 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:

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.

Solution 4 - Java

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 NavigableSet

The SortedSet interface was succeeded by the NavigableSet interface. This newer interface adds features. The same two bundled classes that implement SortedSet, TreeSet & ConcurrentSkipListSet, also implement NavigableSet.

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

Solution 5 - Java

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

Solution 6 - Java

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.

Solution 7 - Java

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.

Solution 8 - Java

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


Solution 9 - Java

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.

Solution 10 - Java

This works:

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

Solution 11 - Java

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

Solution 12 - Java

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.

Solution 13 - Java

Set by definition is not ordered.

You probably use wrong collection.

Solution 14 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKrishPrabakarView Question on Stackoverflow
Solution 1 - JavaSagar KoshtiView Answer on Stackoverflow
Solution 2 - JavaNestor MilyaevView Answer on Stackoverflow
Solution 3 - JavaTaylor HxView Answer on Stackoverflow
Solution 4 - JavaBasil BourqueView Answer on Stackoverflow
Solution 5 - Javahanish.khView Answer on Stackoverflow
Solution 6 - JavaHari MenonView Answer on Stackoverflow
Solution 7 - JavaMumbleskatesView Answer on Stackoverflow
Solution 8 - JavaMasudulView Answer on Stackoverflow
Solution 9 - JavakalakanhuView Answer on Stackoverflow
Solution 10 - JavaRishi BhardwajView Answer on Stackoverflow
Solution 11 - Javauser13156160View Answer on Stackoverflow
Solution 12 - JavaNishant LakharaView Answer on Stackoverflow
Solution 13 - JavaMarcin SzymczakView Answer on Stackoverflow
Solution 14 - JavaChris HagnView Answer on Stackoverflow