How to create a collection from Iterable in java?

For example, I have a set of geometric shapes:

Set<Figure> figures; 

There are two types of shapes: square and circle.

I want to get a set of squares using google collections:

 Iterables.filter(figures,squarePredicate); 

But the filter method returns Iterable ... How to create a Set from Iterable? (without using a loop in Iterable)

+6
source share
6 answers

I think you need to rethink your requirements. You need a set of squares. Why?

Many give you uniqueness and iteration, nothing more. You are unique in Iterable, because the source is a collection, and you can iterate over elements in Iterable. So why do you need a kit?

There are only two possible reasons: either you are working with an API that needs the Set (or Collection) parameter, or you need to somehow display the size of the Set.

In these cases, use Sets.newHashSet(iterable) to create a set (on the one hand, of course, which requires a full iteration, on the other hand: you will need a full iteration at any time when you repeat the values, so why not do it now ?). Otherwise, just use Iterable and forget about the set.

+14
source

If you have Set , you can use Sets.filter rather than Iterables.filter and get the result of Set . This Set is a live view similar to the result of Iterables.filter , but it has Set properties, such as the quick contains method.

To create a copy containing only those elements that match the predicate, you can use ImmutableSet.copyOf or Sets.newHashSet , as others have suggested.

+7
source

Guava Iterables.filter() intentionally returns an iterable "view". There are two advantages to this approach:

  • you only iterate over the elements when you really need to (for example, you can intercept the Iterables.filter () and Iterables.transform () calls and repeat only once at the end).
  • you can create an appropriate collection from the view using something like ImmutableSet.copyOf(Iterables.filter(..., ...)) , Sets.newHashSet(Iterables.filter(..., ...)) or Lists.newArrayList(Iterables.filter(..., ...)) . Iterables.filter () allows you to select the desired collection, rather than returning an arbitrary one.

I also noticed that you seem to be using Iterables.filter (Iterable unfiltered, predicate predicate) with a predicate to filter instances of a certain type, You may also be interested in overloading Iterables.filter (Iterable unfiltered, Class type) , which filters all instances of this type and returns Iterates with a more specific generic type. This avoids uncomfortable throws.

+5
source

Use something like Sets.newHashSet(Iterable) (or Sets.newHashSet(Iterable) you need).

+1
source

Maybe try CollectionUtils.filter() from apache collection utilities? You can use it in a set or use the resulting set in the Set constructor.

+1
source

You can filter the collection and compile it into another collection with Java 8 threads:

 Set<Number> integers = numbers.stream() .filter(x -> x instanceof Integer) .collect(Collectors.toSet()); 

The returned set is a copy, not a live view.

Note that unlike, for example, Guava FluentIterable.filter , the result set is Set<Integer> , because Java does not know that you filtered out all non-integer numbers. If you need Set<Integer> , you need to display after filtering .

 Set<Integer> integers = numbers.stream() .filter(x -> x instanceof Integer) .map(x -> (Integer)x) .collect(Collectors.toSet()); 

(You can combine the filter and the map in flatMap, but this will lead to the appearance of a temporary stream object in one piece and will not be more concise.)

+1
source

Source: https://habr.com/ru/post/899799/