⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 referencemap.java

📁 在Struts2中的jar包xwork的源代码.版本为2.0.7
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/** * Copyright (C) 2006 Google Inc. * * Licensed 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 com.opensymphony.xwork2.inject.util;import static com.opensymphony.xwork2.inject.util.ReferenceType.STRONG;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.lang.ref.Reference;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.HashSet;import java.util.Map;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;/** * Concurrent hash map that wraps keys and/or values in soft or weak * references. Does not support null keys or values. Uses identity equality * for weak and soft keys. * * <p>The concurrent semantics of {@link ConcurrentHashMap} combined with the * fact that the garbage collector can asynchronously reclaim and clean up * after keys and values at any time can lead to some racy semantics. For * example, {@link #size()} returns an upper bound on the size, i.e. the actual * size may be smaller in cases where the key or value has been reclaimed but * the map entry has not been cleaned up yet. * * <p>Another example: If {@link #get(Object)} cannot find an existing entry * for a key, it will try to create one. This operation is not atomic. One * thread could {@link #put(Object, Object)} a value between the time another * thread running {@code get()} checks for an entry and decides to create one. * In this case, the newly created value will replace the put value in the * map. Also, two threads running {@code get()} concurrently can potentially * create duplicate values for a given key. * * <p>In other words, this class is great for caching but not atomicity. * * @author crazybob@google.com (Bob Lee) */@SuppressWarnings("unchecked")public class ReferenceMap<K, V> implements Map<K, V>, Serializable {  private static final long serialVersionUID = 0;  transient ConcurrentMap<Object, Object> delegate;  final ReferenceType keyReferenceType;  final ReferenceType valueReferenceType;  /**   * Concurrent hash map that wraps keys and/or values based on specified   * reference types.   *   * @param keyReferenceType key reference type   * @param valueReferenceType value reference type   */  public ReferenceMap(ReferenceType keyReferenceType,      ReferenceType valueReferenceType) {    ensureNotNull(keyReferenceType, valueReferenceType);    if (keyReferenceType == ReferenceType.PHANTOM        || valueReferenceType == ReferenceType.PHANTOM) {      throw new IllegalArgumentException("Phantom references not supported.");    }    this.delegate = new ConcurrentHashMap<Object, Object>();    this.keyReferenceType = keyReferenceType;    this.valueReferenceType = valueReferenceType;  }  V internalGet(K key) {    Object valueReference = delegate.get(makeKeyReferenceAware(key));    return valueReference == null        ? null        : (V) dereferenceValue(valueReference);  }  public V get(final Object key) {    ensureNotNull(key);    return internalGet((K) key);  }  V execute(Strategy strategy, K key, V value) {    ensureNotNull(key, value);    Object keyReference = referenceKey(key);    Object valueReference = strategy.execute(      this,      keyReference,      referenceValue(keyReference, value)    );    return valueReference == null ? null        : (V) dereferenceValue(valueReference);  }  public V put(K key, V value) {    return execute(putStrategy(), key, value);  }  public V remove(Object key) {    ensureNotNull(key);    Object referenceAwareKey = makeKeyReferenceAware(key);    Object valueReference = delegate.remove(referenceAwareKey);    return valueReference == null ? null        : (V) dereferenceValue(valueReference);  }  public int size() {    return delegate.size();  }  public boolean isEmpty() {    return delegate.isEmpty();  }  public boolean containsKey(Object key) {    ensureNotNull(key);    Object referenceAwareKey = makeKeyReferenceAware(key);    return delegate.containsKey(referenceAwareKey);  }  public boolean containsValue(Object value) {    ensureNotNull(value);    for (Object valueReference : delegate.values()) {      if (value.equals(dereferenceValue(valueReference))) {        return true;      }    }    return false;  }  public void putAll(Map<? extends K, ? extends V> t) {    for (Map.Entry<? extends K, ? extends V> entry : t.entrySet()) {      put(entry.getKey(), entry.getValue());    }  }  public void clear() {    delegate.clear();  }  /**   * Returns an unmodifiable set view of the keys in this map. As this method   * creates a defensive copy, the performance is O(n).   */  public Set<K> keySet() {    return Collections.unmodifiableSet(        dereferenceKeySet(delegate.keySet()));  }  /**   * Returns an unmodifiable set view of the values in this map. As this   * method creates a defensive copy, the performance is O(n).   */  public Collection<V> values() {    return Collections.unmodifiableCollection(        dereferenceValues(delegate.values()));  }  public V putIfAbsent(K key, V value) {    // TODO (crazybob) if the value has been gc'ed but the entry hasn't been    // cleaned up yet, this put will fail.    return execute(putIfAbsentStrategy(), key, value);  }  public boolean remove(Object key, Object value) {    ensureNotNull(key, value);    Object referenceAwareKey = makeKeyReferenceAware(key);    Object referenceAwareValue = makeValueReferenceAware(value);    return delegate.remove(referenceAwareKey, referenceAwareValue);  }  public boolean replace(K key, V oldValue, V newValue) {    ensureNotNull(key, oldValue, newValue);    Object keyReference = referenceKey(key);    Object referenceAwareOldValue = makeValueReferenceAware(oldValue);    return delegate.replace(      keyReference,      referenceAwareOldValue,      referenceValue(keyReference, newValue)    );  }  public V replace(K key, V value) {    // TODO (crazybob) if the value has been gc'ed but the entry hasn't been    // cleaned up yet, this will succeed when it probably shouldn't.    return execute(replaceStrategy(), key, value);  }  /**   * Returns an unmodifiable set view of the entries in this map. As this   * method creates a defensive copy, the performance is O(n).   */  public Set<Map.Entry<K, V>> entrySet() {    Set<Map.Entry<K, V>> entrySet = new HashSet<Map.Entry<K, V>>();    for (Map.Entry<Object, Object> entry : delegate.entrySet()) {      Map.Entry<K, V> dereferenced = dereferenceEntry(entry);      if (dereferenced != null) {        entrySet.add(dereferenced);      }    }    return Collections.unmodifiableSet(entrySet);  }  /**   * Dereferences an entry. Returns null if the key or value has been gc'ed.   */  Entry dereferenceEntry(Map.Entry<Object, Object> entry) {    K key = dereferenceKey(entry.getKey());     V value = dereferenceValue(entry.getValue());    return (key == null || value == null)        ? null        : new Entry(key, value);  }  /**   * Creates a reference for a key.   */  Object referenceKey(K key) {    switch (keyReferenceType) {      case STRONG: return key;      case SOFT: return new SoftKeyReference(key);      case WEAK: return new WeakKeyReference(key);      default: throw new AssertionError();    }  }  /**   * Converts a reference to a key.   */  K dereferenceKey(Object o) {    return (K) dereference(keyReferenceType, o);  }  /**   * Converts a reference to a value.   */  V dereferenceValue(Object o) {    return (V) dereference(valueReferenceType, o);  }  /**   * Returns the refererent for reference given its reference type.   */  Object dereference(ReferenceType referenceType, Object reference) {    return referenceType == STRONG ? reference : ((Reference) reference).get();  }  /**   * Creates a reference for a value.   */  Object referenceValue(Object keyReference, Object value) {    switch (valueReferenceType) {      case STRONG: return value;      case SOFT: return new SoftValueReference(keyReference, value);      case WEAK: return new WeakValueReference(keyReference, value);      default: throw new AssertionError();    }  }  /**   * Dereferences a set of key references.   */  Set<K> dereferenceKeySet(Set keyReferences) {    return keyReferenceType == STRONG        ? keyReferences        : dereferenceCollection(keyReferenceType, keyReferences, new HashSet());  }  /**   * Dereferences a collection of value references.   */  Collection<V> dereferenceValues(Collection valueReferences) {    return valueReferenceType == STRONG        ? valueReferences        : dereferenceCollection(valueReferenceType, valueReferences,            new ArrayList(valueReferences.size()));  }  /**   * Wraps key so it can be compared to a referenced key for equality.   */  Object makeKeyReferenceAware(Object o) {    return keyReferenceType == STRONG ? o : new KeyReferenceAwareWrapper(o);  }  /**   * Wraps value so it can be compared to a referenced value for equality.   */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -