org.apache.mina.util.LazyInitializedCacheMap Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.mina.util;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.mina.core.buffer.IoBuffer;
/**
* This map is specially useful when reads are much more frequent than writes and
* if the cost of instantiating the values is high like allocating an
* {@link IoBuffer} for example.
*
* Based on the final implementation of Memoizer written by Brian Goetz and Tim
* Peierls. This implementation will return an
* {@link UnsupportedOperationException} on each method that is not intended to
* be called by user code for performance reasons.
*
* @param The key type
* @param The value type
*
* @author Apache MINA Project
* @since MINA 2.0.0-M2
*/
public class LazyInitializedCacheMap implements Map {
private ConcurrentMap> cache;
/**
* This class provides a noop {@link LazyInitializer} meaning it
* will return the same object it received when instantiated.
*/
public class NoopInitializer extends LazyInitializer {
private V value;
/**
* Create a new NoopInitializer instance
*
* @param value The value stored in this initializer
*/
public NoopInitializer(V value) {
this.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public V init() {
return value;
}
}
/**
* Default constructor. Uses the default parameters to initialize its internal
* {@link ConcurrentHashMap}.
*/
public LazyInitializedCacheMap() {
this.cache = new ConcurrentHashMap<>();
}
/**
* This constructor allows to provide a fine tuned {@link ConcurrentHashMap}
* to stick with each special case the user needs.
*
* @param map The map to use as a cache
*/
public LazyInitializedCacheMap(ConcurrentHashMap> map) {
this.cache = map;
}
/**
* {@inheritDoc}
*/
@Override
public V get(Object key) {
LazyInitializer c = cache.get(key);
if (c != null) {
return c.get();
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public V remove(Object key) {
LazyInitializer c = cache.remove(key);
if (c != null) {
return c.get();
}
return null;
}
/**
* If the specified key is not already associated
* with a value, associate it with the given value.
* This is equivalent to
*
* if (!map.containsKey(key))
* return map.put(key, value);
* else
* return map.get(key);
* except that the action is performed atomically.
*
* @param key key with which the specified value is to be associated
* @param value a lazy initialized value object.
*
* @return the previous value associated with the specified key,
* or null if there was no mapping for the key
*/
public V putIfAbsent(K key, LazyInitializer value) {
LazyInitializer v = cache.get(key);
if (v == null) {
v = cache.putIfAbsent(key, value);
if (v == null) {
return value.get();
}
}
return v.get();
}
/**
* {@inheritDoc}
*/
@Override
public V put(K key, V value) {
LazyInitializer c = cache.put(key, new NoopInitializer(value));
if (c != null) {
return c.get();
}
return null;
}
/**
* Throws {@link UnsupportedOperationException} as this method would imply
* performance drops.
*/
@Override
public boolean containsValue(Object value) {
throw new UnsupportedOperationException();
}
/**
* Throws {@link UnsupportedOperationException} as this method would imply
* performance drops.
*/
@Override
public Collection values() {
throw new UnsupportedOperationException();
}
/**
* Throws {@link UnsupportedOperationException} as this method would imply
* performance drops.
*/
@Override
public Set> entrySet() {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void putAll(Map extends K, ? extends V> m) {
for (Map.Entry extends K, ? extends V> e : m.entrySet()) {
cache.put(e.getKey(), new NoopInitializer(e.getValue()));
}
}
/**
* @return return the values from the cache
*/
public Collection> getValues() {
return cache.values();
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
cache.clear();
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(Object key) {
return cache.containsKey(key);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty() {
return cache.isEmpty();
}
/**
* {@inheritDoc}
*/
@Override
public Set keySet() {
return cache.keySet();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return cache.size();
}
}