Find element in unordered list by predicate

Assume we have an unordered list of objects and we want to find particular element based on the predicate. As elements can appear in any order, we cannot use any search algorithms, we have to iterate over all the elements in the collection. Let’s check what are the ways of finding such element.

Assume we have a class:

public class Customer {

private String name;

public Customer(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

and the collection:

List<Customer> customers = Arrays.asList(
new Customer("John"),
new Customer("Ted"),
new Customer("Ann"),
new Customer("Joey"));

We will start from Java 6 (because these ways are still actual) and then move to newer versions.

Iterator

public Customer findByName(List<Customer> customers, String name) {
    Iterator<Customer> iterator = customers.iterator();
    while (iterator.hasNext()) {
        Customer customer = iterator.next();
        if (customer.getName().equals(name)) {
            return customer;
        }
    }
    return null;
}

Thanks to the iterator we don’t have to implement the logic of traversing through the collection. We can just check the element the iterator delivers us. In this example we can see there is some boilerplate code according to the use of iterator.

For loop

Customer findByName(List<Customer> customers, String name) {
    for (Customer customer: customers) {
        if (customer.getName().equals(name)) {
            return customer;
        }
    }
return null; }

Iterating using the for loop we can omit the code of using the iterator, it looks much clearer,  but we must remember, that this construction still uses the iterator in the background.

Java 8 Stream

Customer findByName(List<Customer> customers, String name) {
    return customers.stream()
        .filter(customer -> customer.getName().equals(name))
        .findAny()
        .orElse(null);
}

Java 8 introduced new Stream API, which helps us define operations in more declarative way. We only have to implement the predicate (passed to the ‘filter’ method) and the expected result (found element or null). We don’t have to care for implementation details (how the list will be traversed, etc.).

Third-party libraries

Google guava

Guava provides similar functionality to Streams – we can use it in older project, in which we can’t migrate to newer version of Java. 

Customer findByName(List<Customer> customers, String name) {
return Iterables.find(customers, new Predicate<Customer>() {
public boolean apply(Customer customer) {
return customer.getName().equals(name) ;
}
});
}
Apache commons

Another great library, which helps us get a result by using predicate:

Customer findByName(List<Customer> customers, String name) {
return IterableUtils.find(customers, new Predicate<Customer>() {
public boolean evaluate(Customer customer) {
return customer.getName().equals(name);
}
});
}


Dashboard

Leave a Reply

Your email address will not be published. Required fields are marked *