Filter a collection

This example will demonstrate how to filter a collection using java, java 8, guava and apache commons. In the snippets, we have created a NFLTeam class which we will filter all teams that have won a super bowl. A alternate example shows how to filter a list of objects by field in groovy.

An alternate /java/examples/filter-a-collection/

Setup

class NFLTeam {

    private String name;
    private boolean hasWonSuperBowl;


    public NFLTeam(String name, boolean hasWonSuperBowl) {
        super();
        this.name = name;
        this.hasWonSuperBowl = hasWonSuperBowl;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(NFLTeam.class)
                .add("name", name)
                .add("wonsuperbow", hasWonSuperBowl)
                .toString();
    }

    public String getName() {
        return name;
    }

    public boolean hasWonSuperBowl() {
        return hasWonSuperBowl;
    }
}

Straight up Java

Until Java 8, the jdk lacks a mechanism for filtering collections. The only way is to iterate over the collection and then apply criteria. In the snippet below, we will use a enhanced for loop and check if the NFLTeam has won a superbowl.

@Test
public void filter_items_in_list_with_java () {

    List<NFLTeam> nflTeams = Lists.newArrayList();
    nflTeams.add(new NFLTeam("Green Bay Packers", true));
    nflTeams.add(new NFLTeam("Chicago Bears", true));
    nflTeams.add(new NFLTeam("Detroit Lions", false));

    Collection<NFLTeam> superBowlWinners = new ArrayList<NFLTeam>();
    for (NFLTeam team : nflTeams) {
        if (team.hasWonSuperBowl) {
            superBowlWinners.add(team);
        }
    }

    logger.info(superBowlWinners);

    assertTrue(superBowlWinners.size() == 2);
}

Output

[NFLTeam{name=Green Bay Packers, wonsuperbow=true}, NFLTeam{name=Chicago Bears, wonsuperbow=true}]

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 all the NFLTeams that have won a superbowl.

@Test
public void filter_items_in_list_with_java8_lambda () {

    List<NFLTeam> nflTeams = Lists.newArrayList();
    nflTeams.add(new NFLTeam("Green Bay Packers", true));
    nflTeams.add(new NFLTeam("Chicago Bears", true));
    nflTeams.add(new NFLTeam("Detroit Lions", false));


    List<NFLTeam> superBowlWinners = nflTeams
            .stream()
            .filter(p -> p.hasWonSuperBowl)
            .collect(Collectors.toList());

    assertTrue(superBowlWinners.size() == 2);
}

Output

[NFLTeam{name=Green Bay Packers, wonsuperbow=true}, NFLTeam{name=Chicago Bears, wonsuperbow=true}]

Google Guava

Guava Collections2 utility class contains a filter method that encapsulates the looping shown in the straight up java example above. In the snippet below we will create a guava predicate that will return true if the NFLTeam has won a superbowl. Then we will pass the predicate to Collections2.filter which will return the elements that satisfy the predicate.

@Test
public void filter_items_in_list_with_guava () {

    List<NFLTeam> nflTeams = Lists.newArrayList();
    nflTeams.add(new NFLTeam("Green Bay Packers", true));
    nflTeams.add(new NFLTeam("Chicago Bears", true));
    nflTeams.add(new NFLTeam("Detroit Lions", false));

    Collection<NFLTeam> superBowlWinners = Collections2.filter(nflTeams, new Predicate<NFLTeam> () {
        public boolean apply(NFLTeam nflTeam) {
            return nflTeam.hasWonSuperBowl;
        }
    });

    logger.info(superBowlWinners);

    assertTrue(superBowlWinners.size() == 2);
}

Output

[NFLTeam{name=Green Bay Packers, wonsuperbow=true}, NFLTeam{name=Chicago Bears, wonsuperbow=true}]

Apache Commons

Similar to guava and java 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 NFLTeam has won a super bowl and it will remove the elements where it doesn't match this criteria.

@Test
public void filter_items_in_list_with_apache_commons () {

    List<NFLTeam> nflTeams = Lists.newArrayList();
    nflTeams.add(new NFLTeam("Green Bay Packers", true));
    nflTeams.add(new NFLTeam("Chicago Bears", true));
    nflTeams.add(new NFLTeam("Detroit Lions", false));

    CollectionUtils.filter(nflTeams, new org.apache.commons.collections.Predicate() {
        public boolean evaluate(Object nflTeam) {
            return ((NFLTeam) nflTeam).hasWonSuperBowl;
        }
    });

    logger.info(nflTeams);

    assertTrue(nflTeams.size() == 2);
}

Output

[NFLTeam{name=Green Bay Packers, wonsuperbow=true}, NFLTeam{name=Chicago Bears, wonsuperbow=true}]