Reputation: 304
I have a list of objects and I want to create another list, which will include only objects for which the method acceptable()
returns "true". My problem is that I want to make this selection done only on demand. In other words, I want a new list to be calculated and populated only when its iterator()
method is called. Are there any libraries for that in Java?
I'm using JDK7
Upvotes: 4
Views: 260
Reputation: 78
Google Guava has a lot of helper methods for that type of functionality. What you want is already implemented.
Iterators.filter if you want to fiter an Iterator from a collection.
Iterables.filter if you need an instance of Iterable, for example to use it in "for-each" type of loops.
There is also Collections2.filter if you need also other collection methods to be preprocessed with the filter.
Upvotes: 4
Reputation: 1370
I don't know if there are libraries to achieve this, but you could make some sort of list wrapper that does something like this:
public class ResolveList<T extends MyClass> implements Iterable<T> {
//T extends MyClass for access to MyClass.acceptable()
private final List<T> rawList;
private List<T> processedList;
public List<T> getList() {
if(processedList == null) {
processList();
}
return processedList; //check if null
}
public ResolveList(List<T> list) {
this.rawList = list;
}
private void processList() {
processedList = new ArrayList<T>(); //or whatever kind of list you prefer.
for(T t : rawList) {
if(t.acceptable()) {
processedList.add(t);
}
}
}
@Override
public Iterator<T> iterator() {
return this.getList().iterator();
}
}
You could use the built in iterator or get the list itself.
Alternatively you could remove the getList()
function and implement the List<>
interface yourself.
Upvotes: 1
Reputation: 20885
Don't know if there's a library for this, but it's a simple task. This is a LazyIterator:
public class LazyIterator<E extends Acceptable> implements Iterator<E> {
private final Iterator<E> iterator;
private boolean hasNext;
private E next;
public LazyIterator(Iterator<E> iterator) {
this.iterator = iterator;
iterate();
}
private void iterate() {
hasNext = false;
while (iterator.hasNext()) {
next = iterator.next();
if (next.accept()) {
hasNext = true;
break;
}
}
}
@Override public boolean hasNext() { return hasNext; }
@Override public E next() {
if (!hasNext) throw new NoSuchElementException();
E out = next;
iterate();
return out;
}
@Override public void remove() { throw new RuntimeException("N/A"); }
}
And that's the wrapper LazyIterable
public class LazyIterable<E extends Acceptable> implements Iterable<E> {
private final Iterable<E> wrapped;
public LazyIterable(Iterable<E> wrapped) {
this.wrapped = wrapped;
}
@Override
public Iterator<E> iterator() {
return new LazyIterator<E>(wrapped.iterator());
}
}
Here is the full gist with the test and everything
Upvotes: 1
Reputation: 393811
You can use Java 8 Streams:
List<YourClass> list = ...;
Stream<YourClass> filteredList = list.filter(YourClass::acceptable());
Now, only when you run a terminal operation on the Stream, it will consume the source list and find which elements pass the filter.
Upvotes: 1