Monday, April 20, 2009

Fluent assertions, bonus questions

Alex Ruiz tipped me off to an update to FEST, a fluent assertion library. Thanks, Alex!

Bonus questions. Everyone know this idiom:

<K, V> V get(final K key) {
    final V value = concurrentMap.get(key);
    if (null != value) return value;
    concurrentMap.putIfAbsent(key, factoryMethodForV());
    return concurrentMap.get(key);
}

Easier question: How do you support valid null values for the concurrent map? (Hint: monads)

Harder question: Suppose factoryMethodForV() is expensive. How do you guarantee it is only ever called once for a given key?

UPDATE: Fixed some typos.

3 comments:

  1. I'll take a shot at the harder of the two:

    public static interface ValueFactory<K, V> {
     V create(K key);
    }

    public V get(final K key) {
     final ValueHolder<K, V> newValueHolder = new ValueHolder<K, V>(key, this.valueFactory);
     final ValueHolder<K, V> prevValueHolder = this.concurrentMap.putIfAbsent(key, newValueHolder);
     return prevValueHolder != null ? prevValueHolder.value() : newValueHolder.value();
    }

    private static class ValueHolder<K, V> {
     private final Object lock = new Object();
     private final K key;
     private final ValueFactory<K,V> valueFactory;

     private V value;

     private ValueHolder(final K key, final ValueFactory<K, V> valueFactory) {
      this.key = key;
      this.valueFactory = valueFactory;
     }

     private V value() {
      synchronized (this.lock) {
       if (this.value == null) {
        this.value = this.valueFactory.create(this.key);
       }

       return this.value;
      }
     }
    }

    ReplyDelete
  2. I'll take a shot at the harder of the two:

    public static interface ValueFactory<K, V> {
     V create(K key);
    }

    public V get(final K key) {
     final ValueHolder<K, V> newValueHolder = new ValueHolder<K, V>(key, this.valueFactory);
     final ValueHolder<K, V> prevValueHolder = this.concurrentMap.putIfAbsent(key, newValueHolder);
     return prevValueHolder != null ? prevValueHolder.value() : newValueHolder.value();
    }

    private static class ValueHolder<K, V> {
     private final Object lock = new Object();
     private final K key;
     private final ValueFactory<K,V> valueFactory;

     private V value;

     private ValueHolder(final K key, final ValueFactory<K, V> valueFactory) {
      this.key = key;
      this.valueFactory = valueFactory;
     }

     private V value() {
      synchronized (this.lock) {
       if (this.value == null) {
        this.value = this.valueFactory.create(this.key);
       }

       return this.value;
      }
     }
    }

    ReplyDelete
  3. One of the best programmers at work left this comment. Thanks, you know who you are!

    ReplyDelete