Problem
Recently been working on an Android app and had a need to iterate over a collection of non orbitrary objects(ArrayList or List just wouldn't cut it).
The first couple of google searches gave me some stackoverflow answers like this one. Which are helpful but not quite elegant and flexible to use. I personally hate doing this in-line hacks where you create/get an iterator to use in a while loop. It's not obvious at the first glance. And when someone's looking at your code they'd have to figure out whats going on. Surely there should be something better than that.
Solution
The thing I endup using was something that I rarely saw before in any Android app but the solution turned out to be very clean and concise - implement Iterable and Iterator interfaces in a custom class and use it in a for each loop
.
Ok, lets get down to an example:
public class CustomCollectionWrapper implements Iterable<String>, Iterator<String> {
private HashMap<String, Object> internalStorage = new HashMap<String, Object>();
private int count = 0;
public void add(String key, Object value) {
internalStorage.put(key, value);
}
public Object get(String key) {
return internalStorage.get(key);
}
@Override
public boolean hasNext() {
if (count < internalStorage.size()) {
return true;
}
return false;
}
@Override
public String next() {
if (count == internalStorage.size()) throw new IndexOutOfBoundsException();
count++;
return (String) internalStorage.keySet().toArray()[count - 1];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public Iterator<String> iterator() {
return this;
}
}
Now this class can be used in a for_each
loop like this:
CustomCollectionWrapper collectionWrapper = new CustomCollectionWrapper();
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = new Object();
collectionWrapper.add("one", obj1);
collectionWrapper.add("two", obj2);
collectionWrapper.add("three", obj3);
for (String key : collectionWrapper) {
Object obj = collectionWrapper.get(key);
System.out.println("obj = " + obj + " for key: " + key);
}
This is a very neat way to iterate over something, especially more complex than this example, using Java's built in for_each
looping mechanism.
public boolean hasNext()
is called by the loop to see if there is a next element to iterate over.
And public String next()
return to the loop the next element available but it doesn't have to be a String
object. In fact it could be anything: a List
, or Object
, or Integer
, or any other type of class.
Conclusion
This is a relatively easy thing to implement that would give you lots of benefits and especially clear and concise code. You could use it, for example, to iterate over a HashMap using nice and convenient for_each loop.