1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.util; |
7 | |
8 | import java.util.HashMap; |
9 | import java.util.Iterator; |
10 | |
11 | import org.h2.api.ErrorCode; |
12 | import org.h2.message.DbException; |
13 | |
14 | /** |
15 | * A simple hash table with an optimization for the last recently used object. |
16 | */ |
17 | public class SmallMap { |
18 | |
19 | private final HashMap<Integer, Object> map = New.hashMap(); |
20 | private Object cache; |
21 | private int cacheId; |
22 | private int lastId; |
23 | private final int maxElements; |
24 | |
25 | /** |
26 | * Create a map with the given maximum number of entries. |
27 | * |
28 | * @param maxElements the maximum number of entries |
29 | */ |
30 | public SmallMap(int maxElements) { |
31 | this.maxElements = maxElements; |
32 | } |
33 | |
34 | /** |
35 | * Add an object to the map. If the size of the map is larger than twice the |
36 | * maximum size, objects with a low id are removed. |
37 | * |
38 | * @param id the object id |
39 | * @param o the object |
40 | * @return the id |
41 | */ |
42 | public int addObject(int id, Object o) { |
43 | if (map.size() > maxElements * 2) { |
44 | Iterator<Integer> it = map.keySet().iterator(); |
45 | while (it.hasNext()) { |
46 | Integer k = it.next(); |
47 | if (k.intValue() + maxElements < lastId) { |
48 | it.remove(); |
49 | } |
50 | } |
51 | } |
52 | if (id > lastId) { |
53 | lastId = id; |
54 | } |
55 | map.put(id, o); |
56 | cacheId = id; |
57 | cache = o; |
58 | return id; |
59 | } |
60 | |
61 | /** |
62 | * Remove an object from the map. |
63 | * |
64 | * @param id the id of the object to remove |
65 | */ |
66 | public void freeObject(int id) { |
67 | if (cacheId == id) { |
68 | cacheId = -1; |
69 | cache = null; |
70 | } |
71 | map.remove(id); |
72 | } |
73 | |
74 | /** |
75 | * Get an object from the map if it is stored. |
76 | * |
77 | * @param id the id of the object |
78 | * @param ifAvailable only return it if available, otherwise return null |
79 | * @return the object or null |
80 | * @throws DbException if isAvailable is false and the object has not been |
81 | * found |
82 | */ |
83 | public Object getObject(int id, boolean ifAvailable) { |
84 | if (id == cacheId) { |
85 | return cache; |
86 | } |
87 | Object obj = map.get(id); |
88 | if (obj == null && !ifAvailable) { |
89 | throw DbException.get(ErrorCode.OBJECT_CLOSED); |
90 | } |
91 | return obj; |
92 | } |
93 | |
94 | } |