All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.databind.util.LRUMap Maven / Gradle / Ivy

There is a newer version: 2.18.1
Show newest version
package com.fasterxml.jackson.databind.util;

import java.io.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Helper for simple bounded maps used for reusing lookup values.
 *

* Note that serialization behavior is such that contents are NOT serialized, * on assumption that all use cases are for caching where persistence * does not make sense. The only thing serialized is the cache size of Map. *

* NOTE: since version 2.4.2, this is NOT an LRU-based at all; reason * being that it is not possible to use JDK components that do LRU _AND_ perform * well wrt synchronization on multi-core systems. So we choose efficient synchronization * over potentially more efficient handling of entries. *

* And yes, there are efficient LRU implementations such as * concurrentlinkedhashmap; * but at this point we really try to keep external deps to minimum. * Plan from Jackson 2.12 is to focus more on pluggability as {@link LookupCache} and * let users, frameworks, provide their own cache implementations. */ public class LRUMap implements LookupCache, // since 2.12 java.io.Serializable { private static final long serialVersionUID = 1L; protected final transient int _maxEntries; protected final transient ConcurrentHashMap _map; public LRUMap(int initialEntries, int maxEntries) { // We'll use concurrency level of 4, seems reasonable _map = new ConcurrentHashMap(initialEntries, 0.8f, 4); _maxEntries = maxEntries; } @Override public V put(K key, V value) { if (_map.size() >= _maxEntries) { // double-locking, yes, but safe here; trying to avoid "clear storms" synchronized (this) { if (_map.size() >= _maxEntries) { clear(); } } } return _map.put(key, value); } /** * @since 2.5 */ @Override public V putIfAbsent(K key, V value) { // not 100% optimal semantically, but better from correctness (never exceeds // defined maximum) and close enough all in all: if (_map.size() >= _maxEntries) { synchronized (this) { if (_map.size() >= _maxEntries) { clear(); } } } return _map.putIfAbsent(key, value); } // NOTE: key is of type Object only to retain binary backwards-compatibility @Override public V get(Object key) { return _map.get(key); } @Override public void clear() { _map.clear(); } @Override public int size() { return _map.size(); } /* /********************************************************** /* Serializable overrides /********************************************************** */ /** * Ugly hack, to work through the requirement that _value is indeed final, * and that JDK serialization won't call ctor(s) if Serializable is implemented. * * @since 2.1 */ protected transient int _jdkSerializeMaxEntries; private void readObject(ObjectInputStream in) throws IOException { _jdkSerializeMaxEntries = in.readInt(); } private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(_jdkSerializeMaxEntries); } protected Object readResolve() { return new LRUMap(_jdkSerializeMaxEntries, _jdkSerializeMaxEntries); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy