Add Streams.instancesOf(Class, Collection).

This commit is contained in:
Gary Gregory 2021-12-03 13:47:48 -05:00
parent b900dce200
commit e6ae7561a0
3 changed files with 105 additions and 74 deletions

View File

@ -104,6 +104,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="add" dev="ggregory" due-to="Gary Gregory">Add Streams.failableStream(Stream) and deprecate misnamed stream(Stream).</action>
<action type="add" dev="ggregory" due-to="Maxwell Cody, Gary Gregory">Add EnumUtils.getEnumMap(Class, Function). #730</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add FluentBitSet.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add Streams.instancesOf(Class, Collection).</action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Dependabot, Gary Gregory">Bump spotbugs-maven-plugin from 4.2.0 to 4.5.0.0 #735, #808, #822, #834.</action>
<action type="update" dev="ggregory" due-to="Dependabot, XenoAmess">Bump actions/cache from v2.1.4 to v2.1.7 #742, #752, #764, #833.</action>

View File

@ -444,80 +444,6 @@ public class Streams {
}
}
private static <E> Stream<E> filter(final Collection<E> collection, final Predicate<? super E> predicate) {
return toStream(collection).filter(predicate);
}
/**
* Streams non-null elements of a collection.
*
* @param <E> the type of elements in the collection.
* @param collection the collection to stream or null.
* @return A non-null stream that filters out null elements.
* @since 3.13.0
*/
public static <E> Stream<E> nullSafeStream(final Collection<E> collection) {
return filter(collection, Objects::nonNull);
}
/**
* Null-safe version of {@link Stream#of(Object[])}.
*
* @param <T> the type of stream elements.
* @param values the elements of the new stream, may be {@code null}.
* @return the new stream on {@code values} or {@link Stream#empty()}.
* @since 3.13.0
*/
@SafeVarargs // Creating a stream from an array is safe
public static <T> Stream<T> of(final T... values) {
return values == null ? Stream.empty() : Stream.of(values);
}
/**
* Converts the given {@link Collection} into a {@link FailableStream}. This is basically a simplified, reduced version
* of the {@link Stream} class, with the same underlying element stream, except that failable objects, like
* {@link FailablePredicate}, {@link FailableFunction}, or {@link FailableConsumer} may be applied, instead of
* {@link Predicate}, {@link Function}, or {@link Consumer}. The idea is to rewrite a code snippet like this:
*
* <pre>
* {@code
* final List<O> list;
* final Method m;
* final Function<O, String> mapper = (o) -> {
* try {
* return (String) m.invoke(o);
* } catch (Throwable t) {
* throw Failable.rethrow(t);
* }
* };
* final List<String> strList = list.stream().map(mapper).collect(Collectors.toList());
* }
* </pre>
*
* as follows:
*
* <pre>
* {@code
* final List<O> list;
* final Method m;
* final List<String> strList = Failable.stream(list.stream()).map((o) -> (String) m.invoke(o)).collect(Collectors.toList());
* }
* </pre>
*
* While the second version may not be <em>quite</em> as efficient (because it depends on the creation of additional,
* intermediate objects, of type FailableStream), it is much more concise, and readable, and meets the spirit of Lambdas
* better than the first version.
*
* @param <E> The streams element type.
* @param collection The stream, which is being converted.
* @return The {@link FailableStream}, which has been created by converting the stream.
* @deprecated Use {@link #failableStream(Collection)}.
*/
@Deprecated
public static <E> FailableStream<E> stream(final Collection<E> collection) {
return failableStream(collection);
}
/**
* Converts the given {@link Collection} into a {@link FailableStream}. This is basically a simplified, reduced version
* of the {@link Stream} class, with the same underlying element stream, except that failable objects, like
@ -606,6 +532,100 @@ public class Streams {
return new FailableStream<>(stream);
}
private static <E> Stream<E> filter(final Collection<E> collection, final Predicate<? super E> predicate) {
return toStream(collection).filter(predicate);
}
/**
* Streams only instances of the give Class in a collection.
* <p>
* This method shorthand for:
* </p>
* <pre>
* {@code (Stream<E>) Streams.toStream(collection).filter(collection, SomeClass.class::isInstance);}
* </pre>
*
* @param <E> the type of elements in the collection we want to stream.
* @param clazz the type of elements in the collection we want to stream.
* @param collection the collection to stream or null.
* @return A non-null stream that only provides instances we want.
* @since 3.13.0
*/
@SuppressWarnings("unchecked") // After the isInstance check, we still need to type-cast.
public static <E> Stream<E> instancesOf(Class<? super E> clazz, Collection<? super E> collection) {
return (Stream<E>) filter(collection, clazz::isInstance);
}
/**
* Streams non-null elements of a collection.
*
* @param <E> the type of elements in the collection.
* @param collection the collection to stream or null.
* @return A non-null stream that filters out null elements.
* @since 3.13.0
*/
public static <E> Stream<E> nullSafeStream(final Collection<E> collection) {
return filter(collection, Objects::nonNull);
}
/**
* Null-safe version of {@link Stream#of(Object[])}.
*
* @param <T> the type of stream elements.
* @param values the elements of the new stream, may be {@code null}.
* @return the new stream on {@code values} or {@link Stream#empty()}.
* @since 3.13.0
*/
@SafeVarargs // Creating a stream from an array is safe
public static <T> Stream<T> of(final T... values) {
return values == null ? Stream.empty() : Stream.of(values);
}
/**
* Converts the given {@link Collection} into a {@link FailableStream}. This is basically a simplified, reduced version
* of the {@link Stream} class, with the same underlying element stream, except that failable objects, like
* {@link FailablePredicate}, {@link FailableFunction}, or {@link FailableConsumer} may be applied, instead of
* {@link Predicate}, {@link Function}, or {@link Consumer}. The idea is to rewrite a code snippet like this:
*
* <pre>
* {@code
* final List<O> list;
* final Method m;
* final Function<O, String> mapper = (o) -> {
* try {
* return (String) m.invoke(o);
* } catch (Throwable t) {
* throw Failable.rethrow(t);
* }
* };
* final List<String> strList = list.stream().map(mapper).collect(Collectors.toList());
* }
* </pre>
*
* as follows:
*
* <pre>
* {@code
* final List<O> list;
* final Method m;
* final List<String> strList = Failable.stream(list.stream()).map((o) -> (String) m.invoke(o)).collect(Collectors.toList());
* }
* </pre>
*
* While the second version may not be <em>quite</em> as efficient (because it depends on the creation of additional,
* intermediate objects, of type FailableStream), it is much more concise, and readable, and meets the spirit of Lambdas
* better than the first version.
*
* @param <E> The streams element type.
* @param collection The stream, which is being converted.
* @return The {@link FailableStream}, which has been created by converting the stream.
* @deprecated Use {@link #failableStream(Collection)}.
*/
@Deprecated
public static <E> FailableStream<E> stream(final Collection<E> collection) {
return failableStream(collection);
}
/**
* Converts the given {@link Stream stream} into a {@link FailableStream}. This is basically a simplified, reduced
* version of the {@link Stream} class, with the same underlying element stream, except that failable objects, like

View File

@ -137,6 +137,16 @@ public class StreamsTest {
assertEquals(0, Streams.nullSafeStream(Arrays.asList(null, null)).collect(Collectors.toList()).size());
}
@Test
public void testInstanceOfStream() {
assertEquals(2, Streams.instancesOf(String.class, Arrays.asList("A", "B")).collect(Collectors.toList()).size());
assertEquals(2, Streams.instancesOf(String.class, Arrays.asList(null, "A", null, "B", null)).collect(Collectors.toList()).size());
assertEquals(0, Streams.instancesOf(String.class, Arrays.asList(null, null)).collect(Collectors.toList()).size());
//
List<Object> objects = Arrays.asList("A", "B");
assertEquals(2, Streams.instancesOf(String.class, objects).collect(Collectors.toList()).size());
}
@Test
public void testNullSafeStreamNull() {
final List<String> input = null;