View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.util;
21  
22  import java.lang.ref.ReferenceQueue;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Map;
28  import java.util.Set;
29  
30  /**
31   * A Map that uses Soft Reference values internally. Use as a simple cache.
32   *
33   * @param <K> key class
34   * @param <V> value class
35   */
36  public class SoftValueMap<K,V> implements Map<K,V> {
37    private final Map<K, SoftValue<K,V>> internalMap =
38      new HashMap<K, SoftValue<K,V>>();
39    private final ReferenceQueue<?> rq;
40  
41    public SoftValueMap() {
42      this(new ReferenceQueue());
43    }
44  
45    public SoftValueMap(final ReferenceQueue<?> rq) {
46      this.rq = rq;
47    }
48  
49    /**
50     * Checks soft references and cleans any that have been placed on
51     * ReferenceQueue.
52     * @return How many references cleared.
53     */
54    @SuppressWarnings({"unchecked"})
55    public int checkReferences() {
56      int i = 0;
57      for (Object obj; (obj = this.rq.poll()) != null;) {
58        i++;
59        this.internalMap.remove(((SoftValue<K,V>)obj).getKey());
60      }
61      return i;
62    }
63  
64    public V put(K key, V value) {
65      checkReferences();
66      SoftValue<K,V> oldValue = this.internalMap.put(key,
67        new SoftValue<K,V>(key, value, this.rq));
68      return oldValue == null ? null : oldValue.get();
69    }
70  
71    @SuppressWarnings("unchecked")
72    public void putAll(Map map) {
73      throw new RuntimeException("Not implemented");
74    }
75  
76    @SuppressWarnings({"SuspiciousMethodCalls"})
77    public V get(Object key) {
78      checkReferences();
79      SoftValue<K,V> value = this.internalMap.get(key);
80      if (value == null) {
81        return null;
82      }
83      if (value.get() == null) {
84        this.internalMap.remove(key);
85        return null;
86      }
87      return value.get();
88    }
89  
90    public V remove(Object key) {
91      checkReferences();
92      SoftValue<K,V> value = this.internalMap.remove(key);
93      return value == null ? null : value.get();
94    }
95  
96    public boolean containsKey(Object key) {
97      checkReferences();
98      return this.internalMap.containsKey(key);
99    }
100 
101   public boolean containsValue(Object value) {
102 /*    checkReferences();
103     return internalMap.containsValue(value);*/
104     throw new UnsupportedOperationException("Don't support containsValue!");
105   }
106 
107   public boolean isEmpty() {
108     checkReferences();
109     return this.internalMap.isEmpty();
110   }
111 
112   public int size() {
113     checkReferences();
114     return this.internalMap.size();
115   }
116 
117   public void clear() {
118     checkReferences();
119     this.internalMap.clear();
120   }
121 
122   public Set<K> keySet() {
123     checkReferences();
124     return this.internalMap.keySet();
125   }
126 
127   public Set<Map.Entry<K,V>> entrySet() {
128     checkReferences();
129     Set<Map.Entry<K, SoftValue<K,V>>> entries = this.internalMap.entrySet();
130     Set<Map.Entry<K, V>> real_entries = new HashSet<Map.Entry<K,V>>();
131     for(Map.Entry<K, SoftValue<K,V>> entry : entries) {
132       real_entries.add(entry.getValue());
133     }
134     return real_entries;
135   }
136 
137   public Collection<V> values() {
138     checkReferences();
139     Collection<SoftValue<K,V>> softValues = this.internalMap.values();
140     ArrayList<V> hardValues = new ArrayList<V>();
141     for(SoftValue<K,V> softValue : softValues) {
142       hardValues.add(softValue.get());
143     }
144     return hardValues;
145   }
146 }