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);
}
});
}