Initializing a lazy field using lambda

I would like to implement lazy field initialization (or delayed initialization) without an if statement and using lambdas. So, I would like to have the same behavior of the following Foo property, but without if :

 class A<T>{ private T fooField; public T getFoo(){ if( fooField == null ) fooField = expensiveInit(); return fooField; } } 

Ignore the fact that this solution does not guarantee safe use for: 1) multithreading; 2) null as a real value of T

So, to express the intention that the initialization of fooField delayed until its first use, I would like to declare fooField type Supplier<T> , for example:

 class A<T>{ private Supplier<T> fooField = () -> expensiveInit(); public T getFoo(){ return fooField.get(); } } 

and then in the getFoo property, I just go back to fooField.get() . But now I want the following calls to getFoo avoid expensiveInit() and simply return the previous T instance.

How can I achieve this without using if ?

Despite naming conventions and replacing -> with => , this example can also be considered in C #. However, the .NET Framework version 4 already provides Lazy<T> desired semantics.

+45
lambda java-8 lazy-initialization
source share
14 answers

In your real lambda, you can simply update fooField with a new lambda, for example:

 class A<T>{ private Supplier<T> fooField = () -> { T val = expensiveInit(); fooField = () -> val; return val; }; public T getFoo(){ return fooField.get(); } } 

Again, this solution is not thread safe, like .Net Lazy<T> , and does not guarantee that concurrent calls to the getFoo property will return the same result.

+36
source share

Making a decision by Miguel Gamboas and trying to minimize the code for each field without sacrificing its elegance, I came to the following solution:

 interface Lazy<T> extends Supplier<T> { Supplier<T> init(); public default T get() { return init().get(); } } static <U> Supplier<U> lazily(Lazy<U> lazy) { return lazy; } static <T> Supplier<T> value(T value) { return ()->value; } Supplier<Baz> fieldBaz = lazily(() -> fieldBaz=value(expensiveInitBaz())); Supplier<Goo> fieldGoo = lazily(() -> fieldGoo=value(expensiveInitGoo())); Supplier<Eep> fieldEep = lazily(() -> fieldEep=value(expensiveInitEep())); 

The code for each field is slightly larger than in the Stuart Markss solution , but it retains the property of the original solution, which after the first request will be only a lightweight Supplier , which unconditionally returns the already calculated value.

+22
source share

The approach adopted by Miguel Gamboa's Answer is wonderful:

 private Supplier<T> fooField = () -> { T val = expensiveInit(); fooField = () -> val; return val; }; 

This works well for disposable lazy fields. However, if you need to initialize more than one field, you must copy and modify the template template. Another field should be initialized as follows:

 private Supplier<T> barField = () -> { T val = expensiveInitBar(); // << changed barField = () -> val; // << changed return val; }; 

If you can handle one additional method call per access after initialization, I would do it as follows. First, I would write a higher order function that returns a provider instance that contains the cached value:

 static <Z> Supplier<Z> lazily(Supplier<Z> supplier) { return new Supplier<Z>() { Z value; // = null @Override public Z get() { if (value == null) value = supplier.get(); return value; } }; } 

An anonymous class is called here because it has a mutable state that is cached from an initialized value.

Then it becomes quite easy to create many lazily initialized fields:

 Supplier<Baz> fieldBaz = lazily(() -> expensiveInitBaz()); Supplier<Goo> fieldGoo = lazily(() -> expensiveInitGoo()); Supplier<Eep> fieldEep = lazily(() -> expensiveInitEep()); 

Note. I see in the question that it says "without using if ". It was not clear to me whether it was worth worrying about avoiding the excessive working time of the if conditional (in fact, it is rather cheap) or more, to avoid repeating the if conditional condition in each recipient. I suggested that this is the last, and my proposal addresses this concern. If you are worried about exceeding the execution time of the ex-conditional code, then you should also take over the duties of calling the lambda expression.

+20
source share

The Lombok project provides the @Getter(lazy = true) annotation @Getter(lazy = true) , which does exactly what you need.

+10
source share

Supported by

By creating a small interface and combining two new features introduced in java 8:

  • @FunctionalInterface annotation (allows you to assign lambda to the declaration)
  • default keyword (define the implementation as an abstract class, but in the interface)

You can get the same Lazy<T> behavior as in C #.


Using

 Lazy<String> name = () -> "Java 8"; System.out.println(name.get()); 

Lazy.java (copy and paste this interface into an accessible place)

 import java.util.function.Supplier; @FunctionalInterface public interface Lazy<T> extends Supplier<T> { abstract class Cache { private volatile static Map<Integer, Object> instances = new HashMap<>(); private static synchronized Object getInstance(int instanceId, Supplier<Object> create) { Object instance = instances.get(instanceId); if (instance == null) { synchronized (Cache.class) { instance = instances.get(instanceId); if (instance == null) { instance = create.get(); instances.put(instanceId, instance); } } } return instance; } } @Override default T get() { return (T) Cache.getInstance(this.hashCode(), () -> init()); } T init(); } 

Online example - https://ideone.com/3b9alx

The following snippet demonstrates the life cycle of this helper class.

 static Lazy<String> name1 = () -> { System.out.println("lazy init 1"); return "name 1"; }; static Lazy<String> name2 = () -> { System.out.println("lazy init 2"); return "name 2"; }; public static void main (String[] args) throws java.lang.Exception { System.out.println("start"); System.out.println(name1.get()); System.out.println(name1.get()); System.out.println(name2.get()); System.out.println(name2.get()); System.out.println("end"); } 

displays

 start lazy init 1 name 1 name 1 lazy init 2 name 2 name 2 end 

See online demo - https://ideone.com/3b9alx

+3
source share

How about this? then you can do something like this using the LazyInitializer from Apache Commons: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/concurrent/LazyInitializer.html

 private static Lazy<Double> _lazyDouble = new Lazy<>(()->1.0); class Lazy<T> extends LazyInitializer<T> { private Supplier<T> builder; public Lazy(Supplier<T> builder) { if (builder == null) throw new IllegalArgumentException(); this.builder = builder; } @Override protected T initialize() throws ConcurrentException { return builder.get(); } } 
+2
source share

You can do something in this direction:

  private Supplier heavy = () -> createAndCacheHeavy(); public Heavy getHeavy() { return heavy.get(); } private synchronized Heavy createAndCacheHeavy() { class HeavyFactory implements Supplier { private final Heavy heavyInstance = new Heavy(); public Heavy get() { return heavyInstance; } } if(!HeavyFactory.class.isInstance(heavy)) { heavy = new HeavyFactory(); } return heavy.get(); } 

I recently saw this as the idea of ​​Venkat Subramanyam. I copied the code for this page .

The basic idea is that once a provider is called, it replaces a simpler factory implementation that returns an initialized instance.

This was in the context of thread safe lazy singleton initialization, but you could also apply it to a normal field.

+1
source share

This also works if you want to pass arguments (which you do not have when initializing the functional interface) to your expensiveInit method.

 public final class Cache<T> { private Function<Supplier<? extends T>, T> supplier; private Cache(){ supplier = s -> { T value = s.get(); supplier = n -> value; return value; }; } public static <T> Supplier<T> of(Supplier<? extends T> creater){ Cache<T> c = new Cache<>(); return () -> c.supplier.apply(creater); } public static <T, U> Function<U, T> of(Function<? super U, ? extends T> creater){ Cache<T> c = new Cache<>(); return u -> c.supplier.apply(() -> creater.apply(u)); } public static <T, U, V> BiFunction<U, V, T> of(BiFunction<? super U, ? super V, ? extends T> creater){ Cache<T> c = new Cache<>(); return (u, v) -> c.supplier.apply(() -> creater.apply(u, v)); } } 

Usage is the same as Stuart Marks' :

 private final Function<Foo, Bar> lazyBar = Cache.of(this::expensiveBarForFoo); 
+1
source share

If you need something that approximates Lazy behavior in C #, which gives you thread safety and ensures that you always get the same value, there is no easy way to avoid if .

You will need to use an unstable field and a double lock check. Below is the lowest memory version for a class that gives you C # behavior:

 public abstract class Lazy<T> implements Supplier<T> { private enum Empty {Uninitialized} private volatile Object value = Empty.Uninitialized; protected abstract T init(); @Override public T get() { if (value == Empty.Uninitialized) { synchronized (this) { if (value == Empty.Uninitialized) { value = init(); } } } return (T) value; } } 

It is not so elegant. You will have to create lazy values, for example:

 final Supplier<Baz> someBaz = new Lazy<Baz>() { protected Baz init(){ return expensiveInit(); } } 

You can get some elegance from the extra memory by adding the factory method as follows:

  public static <V> Lazy<V> lazy(Supplier<V> supplier) { return new Lazy<V>() { @Override protected V init() { return supplier.get(); } }; } 

Now you can create thread safe lazy values ​​just like this:

 final Supplier<Foo> lazyFoo = lazy(() -> fooInit()); final Supplier<Bar> lazyBar = lazy(() -> barInit()); final Supplier<Baz> lazyBaz = lazy(() -> bazInit()); 
+1
source share

Well, actually I do not propose not to have an “if”, but here is my opinion on this issue:

One simple method is to use an AtomicReference (the ternary operator still looks like an if):

 private final AtomicReference<Something> lazyVal = new AtomicReference<>(); void foo(){ final Something value = lazyVal.updateAndGet(x -> x != null ? x : expensiveCreate()); //... } 

But there is a whole thread safety magic that might not be needed. So I would do it like Miguel with a slight twist:

Since I like simple one-liners, I just use the ternary operator (again, reads like an “if”), but I would let the Java evaluation order do its magic to set the field:

 public static <T> Supplier<T> lazily(final Supplier<T> supplier) { return new Supplier<T>() { private T value; @Override public T get() { return value != null ? value : (value = supplier.get()); } }; } 

The above example of modifying the gerardw field, which works without an "if", can also be further simplified. We do not need an interface. We just need to use the above “trick” again: the result of the assignment operator is the assigned value, we can use parentheses to force the calculation order. So with the method above it is simple:

 static <T> Supplier<T> value(final T value) { return () -> value; } Supplier<Point> p2 = () -> (p2 = value(new Point())).get(); 

Note that you cannot use the value (...) method without losing laziness.

+1
source share

How about this one. Some J8 function switches to avoid ifs for every access. Warning: no thread is known.

 import java.util.function.Supplier; public class Lazy<T> { private T obj; private Supplier<T> creator; private Supplier<T> fieldAccessor = () -> obj; private Supplier<T> initialGetter = () -> { obj = creator.get(); creator = null; initialGetter = null; getter = fieldAccessor; return obj; }; private Supplier<T> getter = initialGetter; public Lazy(Supplier<T> creator) { this.creator = creator; } public T get() { return getter.get(); } } 
0
source share

Stuart Mark solution with explicit class. (I think this is "better" - this is a personal preference).

 public class ScriptTrial { static class LazyGet<T> implements Supplier<T> { private T value; private Supplier<T> supplier; public LazyGet(Supplier<T> supplier) { value = null; this.supplier = supplier; } @Override public T get() { if (value == null) value = supplier.get(); return value; } } Supplier<Integer> lucky = new LazyGet<>(()->seven()); int seven( ) { return 7; } @Test public void printSeven( ) { System.out.println(lucky.get()); System.out.println(lucky.get()); } 

}

0
source share

2 solutions, one functional and then one object (this is the same code), thread-safe , without an "if" and take care of handling exceptions with the correct type propagation (there is no solution to take care of this).

This is pretty short. The best lazy field support handled by the runtime will ultimately make this code obsolete ...

using:

 // object version : 2 instances (object and lambda) final Lazy<Integer, RuntimeException> lazyObject = new LazyField<>(() -> 1); // functional version : more efficient than object, 1 instance // usage : wrap computed value using eval(arg), and set the lazy field with result Lazy<Service, IOException> lazyFunc = lazyField(() -> this.lazyFunc = eval(new Service())); // functional final version, as field is final this is less efficient than object : // 2 instances and one "if". null check removal may remove the "if"... final Lazy<Integer, RuntimeException> finalFunc = lazyField(() -> eval(1)); // Here the checked exception type thrown in lambda can only be ServiceException static Lazy<Integer, ServiceException> lazyTest = lazyField(() -> {throw new ServiceException();}); 

First I define a lambda with the exception of:

 @FunctionalInterface interface SupplierWithException<T, E extends Exception> { T get() throws E; } 

Then the lazy type:

 interface Lazy<T, E extends Exception> extends SupplierWithException<T, E> {} 

Functional Version:

It directly returns a lambda, which ultimately gets less memory if not used in the final field, as in the example above.

 static <T, E extends Exception> Lazy<T, E> lazyField(Lazy<Lazy<T, E>, E> value) { Objects.requireNonNull(value); Lazy<T, E>[] field = new Lazy[1]; return () -> { if(field[0] == null) { synchronized(field) { if(field[0] == null) { field[0] = value.get(); } } } return field[0].get(); }; } static <T, E extends Exception> Lazy<T, E> eval(T value) { return () -> value; } 

You cannot be forced to give the correct value for the callback, at least it always returns the same result, but cannot avoid the "if" (as in the latter case of the field).

Object Version:

It is completely safe outside.

 public final class LazyField<T, E extends Exception> implements Lazy<T, E> { private Lazy<T, E> value; public LazyField(SupplierWithException<T, E> supplier) { value = lazyField(() -> value = eval(supplier.get())); } @Override public T get() throws E { return value.get(); } } 

enjoy

0
source share

Here is a solution using Java Proxy (reflection) and the Java 8 provider.

* Due to the use of a proxy, the initiated object must implement the transferred interface.

* The difference from other solutions is the encapsulation of initiation from use. You start working directly with the DataSource , as if it were initialized. It will be initialized the first time the method is called.

Application:

 DataSource ds = LazyLoadDecorator.create(() -> initSomeDS(), DataSource.class) 

Behind the scenes:

 public class LazyLoadDecorator<T> implements InvocationHandler { private final Object syncLock = new Object(); protected volatile T inner; private Supplier<T> supplier; private LazyLoadDecorator(Supplier<T> supplier) { this.supplier = supplier; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (inner == null) { synchronized (syncLock) { if (inner == null) { inner = load(); } } } return method.invoke(inner, args); } protected T load() { return supplier.get(); } @SuppressWarnings("unchecked") public static <T> T create(Supplier<T> supplier, Class<T> clazz) { return (T) Proxy.newProxyInstance(LazyLoadDecorator.class.getClassLoader(), new Class[] {clazz}, new LazyLoadDecorator<>(supplier)); } } 
-one
source share

All Articles