Poor man's lazy evaluation in Java 8 I have an class that cheaply imitates a lazy evaluation scheme. The class is for representing a file and additionally providing meta data on the file.  Some of the meta-data can be expensive to evaluate so I only want to evaluate it when requested, and only evaluate it once.

My implementation is such: All private members are stored in an EnumMap and each member is associated with a value in the enum Field.

private enum Field {
    FILE_CODE
    //, ...
};
private Map&lt;Field, Optional&gt; lazyAttributes = new EnumMap&lt;Field, Optional&gt;(Field.class);


The values in the EnumMap are Optionals in case evaluation failed (value not in database etc.)  Accessors methods get the member by providing the Field value associated with the member and a Supplier which will evaluate member if it hasn't yet been evaluated.

private &lt;T&gt; Optional&lt;T&gt; lazyLookup(Field field, Supplier&lt;Optional&lt;T&gt;&gt; answer) {
    if (lazyAttributes.containsKey(field)) { // field was already evaluated, get answer.
        return lazyAttributes.get(field);    // unchecked Optional to Optional&lt;T&gt;
    } else {                                 // field is unevaluated;
        Optional result = answer.get();      // evaluate,
        lazyAttributes.put(field, result);   // then store
        return result;                       // unchecked Optional to Optional&lt;T&gt;
    }
}


This is an example of what an accessor looks like.

public Optional&lt;String&gt; getFileCode() {
    return lazyLookup(Field.FILE_CODE, 
            () -&gt; FileCodeKeyWords.apply(getName())); // consider this expensive
}


I am concerned about the unchecked operations in lazyLookup and it seems to be an overly complicated setup.  I can provide the rest of the class if requested.
Your lazy method is not thread safe. If two threads check for the key at the same time they will both find it absent and both create a new object.

Wrapping your EnumMap in a ConcurrentMap will get around this.

private ConcurrentMap&lt;Field, Optional&gt; lazyThreadSafeAttributes = new ConcurrentHashMap(lazyAttributes);

private &lt;T&gt; Optional&lt;T&gt; lazyThreadSafeLookup(Field field, Supplier&lt;Optional&lt;T&gt;&gt; answer) {
    return lazyThreadSafeAttributes.computeIfAbsent(field, k -&gt; answer.get());
}