Guava
As your [Guava] tag suggests, most Guava collection operations are lazy - they are applied only once needed. For example:
List<String> strings = Lists.newArrayList("1", "2", "3");
List<Integer> integers = Lists.transform(strings, new Function<String, Integer>() {
@Override
public Integer apply(String input) {
System.out.println(input);
return Integer.valueOf(input);
}
});
This code seems to convert a List<String>
to a List<Integer>
while also writing the strings to the output. But if you actually run it, it doesn't do anything. Let's add some more code:
for (Integer i : integers) {
// nothing to do
}
Now it writes the inputs out!
That's because the Lists.transform()
method doesn't actually do the transforming, but returns a specially crafted class which only computes the values when they are needed.
Bonus proof that it all works nicely: If we removed the empty loop and replaced it with e.g. just integers.get(1);
, it would actually only output the number 2
.
If you'd like to chain multiple methods together, there is always FluentIterable
. That basically allows you to code in the Java 8 Stream-like style.
Goldman Sachs Collections
While Guava usually does the right thing by default and works with JDK classes, sometimes you need something more complex. That's where Goldman Sachs collections come in. GS collections give you far more flexibility and power by having a complete drop-in collections framework with everything you might dream of. Laziness is not theer by default, but can be easily achieved:
FastList<String> strings = FastList.newListWith("1", "2", "3");
LazyIterable<Integer> integers = strings.asLazy().collect(new Function<String, Integer>() {
@Override
public Integer valueOf(String string) {
System.out.println(string);
return Integer.valueOf(string);
}
});
Again, doesn't do anything. But:
for (Integer i : integers) {
// nothing to do
}
suddenly outputs everything.