2 * Copyright (C) 2006 Robin Rosenberg <robin.rosenberg@dewire.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.jgit
.lib
;
19 import java
.lang
.reflect
.InvocationTargetException
;
20 import java
.lang
.reflect
.Method
;
21 import java
.util
.AbstractMap
;
22 import java
.util
.AbstractSet
;
23 import java
.util
.Iterator
;
26 import java
.util
.TreeMap
;
29 * Very much like a map, but specialized to partition the data on the first byte
30 * of the key. This is about twice as fast. See test class.
32 * Inspiration is taken from the Git pack file format which uses this technique
33 * to improve lookup performance.
36 * The value we map ObjectId's to.
39 public class ObjectIdMap
<V
> extends AbstractMap
<ObjectId
, V
> {
41 @SuppressWarnings("unchecked")
42 final Map
<ObjectId
, V
>[] level0
= new Map
[256];
45 * Construct an ObjectIdMap with an underlying TreeMap implementation
47 public ObjectIdMap() {
52 * Construct an ObjectIdMap with the same underlying map implementation as
53 * the provided example.
57 @SuppressWarnings("unchecked")
58 public ObjectIdMap(Map sample
) {
60 Method m
=sample
.getClass().getMethod("clone", (Class
[])null);
61 for (int i
=0; i
<256; ++i
) {
62 level0
[i
] = (Map
)m
.invoke(sample
, (Object
[])null);
64 } catch (IllegalAccessException e
) {
65 throw new IllegalArgumentException(e
);
66 } catch (IllegalArgumentException e
) {
67 throw new IllegalArgumentException(e
);
68 } catch (InvocationTargetException e
) {
69 throw new IllegalArgumentException(e
);
70 } catch (SecurityException e
) {
71 throw new IllegalArgumentException(e
);
72 } catch (NoSuchMethodException e
) {
73 throw new IllegalArgumentException(e
);
78 for (int i
=0; i
<256; ++i
)
82 public boolean containsKey(Object key
) {
83 return submap((ObjectId
)key
).containsKey(key
);
86 private final Map
<ObjectId
, V
> submap(ObjectId key
) {
87 return level0
[key
.getFirstByte()];
90 public boolean containsValue(Object value
) {
91 for (int i
=0; i
<256; ++i
)
92 if (level0
[i
].containsValue(value
))
97 private Set
<Map
.Entry
<ObjectId
, V
>> entrySet
=
98 new AbstractSet
<Map
.Entry
<ObjectId
, V
>>() {
101 final public Iterator
<Map
.Entry
<ObjectId
, V
>> iterator() {
102 return new Iterator
<Entry
<ObjectId
,V
>>() {
103 private int levelIndex
;
104 private boolean hasNext
;
105 private Iterator
<Map
.Entry
<ObjectId
, V
>> levelIterator
;
106 private Iterator
<Map
.Entry
<ObjectId
, V
>> lastIterator
;
110 public boolean hasNext() {
113 public java
.util
.Map
.Entry
<ObjectId
, V
> next() {
114 Entry
<ObjectId
, V
> ret
= levelIterator
.next();
118 public void remove() {
119 lastIterator
.remove();
122 private void step() {
124 lastIterator
= levelIterator
;
125 while ((levelIterator
==null || !(hasNext
=levelIterator
.hasNext()))) {
126 if (levelIndex
< level0
.length
)
127 levelIterator
= level0
[levelIndex
++].entrySet().iterator();
138 for (int i
=0; i
<256; ++i
)
139 ret
+= level0
[i
].size();
145 public Set
<Map
.Entry
<ObjectId
, V
>> entrySet() {
149 public V
get(Object key
) {
150 return submap((ObjectId
)key
).get(key
);
153 public boolean isEmpty() {
154 for (int i
=0; i
<256; ++i
)
155 if (!level0
[i
].isEmpty())
160 @SuppressWarnings("unchecked")
161 public V
put(ObjectId key
, V value
) {
162 return submap(key
).put(key
, value
);
165 public void putAll(Map
<?
extends ObjectId
, ?
extends V
> arg0
) {
166 for (ObjectId k
: arg0
.keySet()) {
172 public V
remove(Object key
) {
173 return submap((ObjectId
) key
).remove(key
);
177 return entrySet().size();