Getting an arbitrary item from a set

In many algorithms, you have to iterate over a set of elements, and the set is not empty.

Since you can change a set during iteration, you usually pull an element out of the set and then iterate, possibly adding or removing elements from or from the set. Here is a typical Java code for this.

Set<Integer> possibleFactors = Sets.newHashSet(2,3,4,5,6,7,8,100); while (!possibleFactors.isEmpty()) { int factor = possibleFactors.iterator().next(); for (int i=1;i<10;i++) possibleFactors.remove(i*factor); } 

edit: As stated in the comments, I will give a better example. I repeat the files selected by the user and I filter them by checking the permissions of each element. However, as an optimization, if the user does not have permission for a specific directory, I will remove all files from it from the set.

 Set<Path> input = Sets.newHashSet(userSelectedPaths); while (!input.isEmpty()) { Path path = input.iterator.next(); input.remove(path); if (!expensivePermissionCheck(path)) { input.removeAll(path.getFiles()); } else { processPath(path); } } 

However, the first line in the loop looks strange. It creates superfluous Iterable objects, when all I want is an arbitrary element from the set, it doesn't matter to me in which order.

Besides performance, it looks weird and less readable.

Is there a better alternative? Maybe a completely different structure?

edit: Perhaps the best wording would be, "How do I place an arbitrary element from a set?"

+7
source share
3 answers

The only access methods for Set are the iterator() or toArray() methods.

If you have a SortedSet , you can use the first() or last() method to access a single element directly.

+4
source

In fact, it is not only unreadable, but also throws an exception if the collection is empty.

Before you get next() , you should always check hasNext() and then act on that.

-one
source

There is no special ordering of elements in the set. You can remove or check for the presence of an element by specifying its value (Set.remove (Object o) or Set.contains (Object o). You can consider removing all elements from the set or rephrasing it, keeping the elements in set A that are not in set B using

 Set.removeAll(Set B); 

for example

 Set<Integer> A = new HashSet(); Set<Integer> B = new HashSet(); add numbers from 1-to-10 into A add even numbers in range [1, 10] to B A.removeAll(B); println(A) will print all odd numbers, eg those that are in A but not in B. 

Alternatively, you can call the remove () method, which removes the element from the set, if it exists:

 for (int i = 2; i <= 10; i += 2) { a.remove(i) } 

It will have the same effect as removeAll () in the above example.

As a rule, the Set data structure is suitable when you work with collections of unique things, and their ordering does not matter. Sets are useful (and fast) if you want to perform the operations of "Union", "Intersection", "Diff", etc. On sets. If you have items that can be repeated again, then you might consider using Multisets (google collections) if you want to arrange things, then lists will be more useful (but with worse performance).

-2
source

All Articles