2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.lib
;
40 import java
.lang
.reflect
.InvocationTargetException
;
41 import java
.lang
.reflect
.Method
;
42 import java
.util
.AbstractMap
;
43 import java
.util
.AbstractSet
;
44 import java
.util
.Iterator
;
47 import java
.util
.TreeMap
;
50 * Very much like a map, but specialized to partition the data on the first byte
51 * of the key. This is about twice as fast. See test class.
53 * Inspiration is taken from the Git pack file format which uses this technique
54 * to improve lookup performance.
57 * The value we map ObjectId's to.
60 public class ObjectIdMap
<V
> extends AbstractMap
<ObjectId
, V
> {
62 @SuppressWarnings("unchecked")
63 final Map
<ObjectId
, V
>[] level0
= new Map
[256];
66 * Construct an ObjectIdMap with an underlying TreeMap implementation
68 public ObjectIdMap() {
73 * Construct an ObjectIdMap with the same underlying map implementation as
74 * the provided example.
78 @SuppressWarnings("unchecked")
79 public ObjectIdMap(Map sample
) {
81 Method m
=sample
.getClass().getMethod("clone", (Class
[])null);
82 for (int i
=0; i
<256; ++i
) {
83 level0
[i
] = (Map
)m
.invoke(sample
, (Object
[])null);
85 } catch (IllegalAccessException e
) {
86 throw new IllegalArgumentException(e
);
87 } catch (IllegalArgumentException e
) {
88 throw new IllegalArgumentException(e
);
89 } catch (InvocationTargetException e
) {
90 throw new IllegalArgumentException(e
);
91 } catch (SecurityException e
) {
92 throw new IllegalArgumentException(e
);
93 } catch (NoSuchMethodException e
) {
94 throw new IllegalArgumentException(e
);
99 for (int i
=0; i
<256; ++i
)
103 public boolean containsKey(Object key
) {
104 return submap((ObjectId
)key
).containsKey(key
);
107 private final Map
<ObjectId
, V
> submap(ObjectId key
) {
108 return level0
[key
.getFirstByte()];
111 public boolean containsValue(Object value
) {
112 for (int i
=0; i
<256; ++i
)
113 if (level0
[i
].containsValue(value
))
118 private Set
<Map
.Entry
<ObjectId
, V
>> entrySet
=
119 new AbstractSet
<Map
.Entry
<ObjectId
, V
>>() {
122 final public Iterator
<Map
.Entry
<ObjectId
, V
>> iterator() {
123 return new Iterator
<Entry
<ObjectId
,V
>>() {
124 private int levelIndex
;
125 private boolean hasNext
;
126 private Iterator
<Map
.Entry
<ObjectId
, V
>> levelIterator
;
127 private Iterator
<Map
.Entry
<ObjectId
, V
>> lastIterator
;
131 public boolean hasNext() {
134 public java
.util
.Map
.Entry
<ObjectId
, V
> next() {
135 Entry
<ObjectId
, V
> ret
= levelIterator
.next();
139 public void remove() {
140 lastIterator
.remove();
143 private void step() {
145 lastIterator
= levelIterator
;
146 while ((levelIterator
==null || !(hasNext
=levelIterator
.hasNext()))) {
147 if (levelIndex
< level0
.length
)
148 levelIterator
= level0
[levelIndex
++].entrySet().iterator();
159 for (int i
=0; i
<256; ++i
)
160 ret
+= level0
[i
].size();
166 public Set
<Map
.Entry
<ObjectId
, V
>> entrySet() {
170 public V
get(Object key
) {
171 return submap((ObjectId
)key
).get(key
);
174 public boolean isEmpty() {
175 for (int i
=0; i
<256; ++i
)
176 if (!level0
[i
].isEmpty())
181 @SuppressWarnings("unchecked")
182 public V
put(ObjectId key
, V value
) {
183 return submap(key
).put(key
, value
);
186 public void putAll(Map
<?
extends ObjectId
, ?
extends V
> arg0
) {
187 for (ObjectId k
: arg0
.keySet()) {
193 public V
remove(Object key
) {
194 return submap((ObjectId
) key
).remove(key
);
198 return entrySet().size();