I hope this closure-style finding methods provide more human readable sourcecode instead of for-looping.
I've needed to search object(s) in List. In the first place, I repeated for-loops to get objects and check whether it matches criteria. Unfortunately, it was not clean-looking-sorucecode for me.
Unfortunately, only final variables are allowed in callback implementation.
Sample Usage(Junit style)
public class SearcherTest {
private List<Person> people;
private Person p1 = new Person("foo", 1);
private Person p2 = new Person("bar", 2);
private Person p3 = new Person("baz", 3);
private CollectionSearcher<Person> searcher;
@Before
public void setUp() {
people = new ArrayList<Person>();
people.add(p1);
people.add(p2);
people.add(p3);
searcher = new CollectionSearcher<Person>(people);
}
@Test
public void testFind() {
Person result = searcher.find(new SearchStrategy<Person>() {
public boolean isEqual(Person person) {
return person.getName().equals("bar");
}
});
assertSame(p2, result);
}
@Test
public void testFindAll() {
List<Person> result = searcher.findAll(new SearchStrategy<Person>() {
public boolean isEqual(Person person) {
return person.getName().startsWith("b");
}
});
assertEquals(2, result.size());
assertSame(p2, result.get(0));
assertSame(p3, result.get(1));
}
@Test
public void testCollect() {
List<Person> result = searcher.collect(new CollectStrategy<Person>() {
public Person compare(Person person) {
if (person.getId() > 2) {
return person;
}
return null;
}
});
assertEquals(1, result.size());
assertEquals(3, result.get(0).getId());
}
@Test
public void testIndexOf() {
int index = searcher.indexOf(new SearchStrategy<Person>() {
public boolean isEqual(Person person) {
return person.getName().equals("baz");
}
});
assertEquals(2, index);
}
@Test
public void testContains() {
boolean result = searcher.contains(new SearchStrategy<Person>() {
public boolean isEqual(Person person) {
return person.getName().equals("baz");
}
});
assertTrue(result);
result = searcher.contains(new SearchStrategy<Person>() {
public boolean isEqual(Person person) {
return person.getName().equals("foobar");
}
});
assertFalse(result);
}
static class Person {
private String name;
private int id;
public Person(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
}
Implemenatation
public class CollectionSearcher<E> {
private Collection<E> collection;
public CollectionSearcher() {
}
public CollectionSearcher(Collection<E> collection) {
this.collection = collection;
}
/**
* return the first element that given strategy returns true
*
* @param strategy
* @return
*/
public E find(SearchStrategy<E> strategy) {
for (E entry : collection) {
if (strategy.isEqual(entry)) return entry;
}
return null;
}
/**
* returns all element that given strategy returns true
*
* @param strategy
* @return
*/
public List<E> findAll(SearchStrategy<E> strategy) {
List<E> results = new ArrayList<E>();
for (E entry : collection) {
if (strategy.isEqual(entry)) results.add(entry);
}
return results;
}
/**
* return list of elements that strategy returns
* if strategy returns null, then it won't be in the list
*
* @param strategy
* @return
*/
public List<E> collect(CollectStrategy<E> strategy) {
List<E> results = new ArrayList<E>();
for (E entry : collection) {
E result = strategy.compare(entry);
if (result != null) results.add(result);
}
return results;
}
/**
* returns the first index of element that strategy returns true, or -1 if none of the element satisfies the strategy
*
* @param strategy
* @return
*/
public int indexOf(SearchStrategy<E> strategy) {
int index = 0;
for (E entry : collection) {
if (strategy.isEqual(entry)) return index;
index++;
}
return -1;
}
/**
* returns true if the collection has an element that satisfies given strategy
* @param strategy
* @return
*/
public boolean contains(SearchStrategy<E> strategy) {
for (E entry : collection) {
if (strategy.isEqual(entry)) return true;
}
return false;
}
public Collection<E> getCollection() {
return collection;
}
public void setCollection(Collection<E> collection) {
this.collection = collection;
}
}
Search Strategies
public interface CollectStrategy<T> {
T compare(T object);
}
public interface SearchStrategy<T> {
/**
* Returns true if the given object satsfies criteria
* @param object
* @return
*/
boolean isEqual(T object);
}