This example will demonstrates how to filter a collection by a java class type using java, java 8, guava and apache commons.
Setup
List<Object> objects;
@Before
public void setUp () {
objects = Lists.newArrayList();
objects.add(new Integer(15));
objects.add(new Double(12));
objects.add("hello");
objects.add(Lists.newArrayList());
objects.add(Maps.newConcurrentMap());
objects.add("world");
}
Straight up Java
Until Java 8, the jdk did not have a way to filter a collection unless you iterate over the collection and then apply criteria. In the snippet below, we will use a enhanced for loop using the instanceOf keyword to check if it is of class String.
@Test
public void filter_elements_by_type_java () {
List<String> strings = new ArrayList<String>();
for (Object obj : objects) {
if (obj instanceof String) {
strings.add((String) obj);
}
}
assertThat(strings, contains(
"hello", "world"));
}
Java 8
Java 8 introduced the stream api which allows you to write powerful code in just a few lines. Streams filter is an intermediate operation that will return a stream consisting of the elements that match the specified predicate. In the snippet below, through a lambda expression we will create a java predicate that will filter elements where the class type equals a string.
@Test
public void filter_elements_by_type_java8_lambda () {
List<String> strings = objects
.stream()
.filter(p -> p instanceof String)
.map(p -> (String) p)
.collect(Collectors.toList());
System.out.println(strings);
assertThat(strings, contains(
"hello", "world"));
}
Google Guava
Both guava Iterables and FluentIterable utility class contain an overloaded filter method that accepts a Class type parameter. It will return all elements from the collection equaling the parameter type.
Using FluentIterable
@Test
public void filter_elements_by_type_guava_fluentiterable () {
List<String> strings = FluentIterable.from(objects)
.filter(String.class)
.toList();
assertThat(strings, contains(
"hello", "world"));
}
Using Iterables
@Test
public void filter_elements_by_type_iterable () {
Iterable<String> strings = Iterables.filter(objects, String.class);
assertThat(strings, contains(
"hello", "world"));
}
Apache Commons
Similar to java and guava predicate, apache commons has a predicate class as well. Below we will call CollectionsUtils.filter passing it a predicate that will return true if the object is of class type String and it will remove the elements where it doesn't match this criteria.
@Test
public void filter_elements_by_type_apache () {
CollectionUtils.filter(objects, new org.apache.commons.collections.Predicate() {
public boolean evaluate(Object obj) {
return obj instanceof String;
}
});
@SuppressWarnings("unchecked")
Collection<String> strings = CollectionUtils.typedCollection(objects, String.class);
assertThat(strings, contains(
"hello", "world"));
}