Rev 97 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (c) 2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.splitter;
/**
* A map from int to Object, designed to minimise memory use while still maintaining
* good performance.
* <p/>
* It doesn't behave exactly the same way as a map would. Note also that zero is
* reserved and should not be used as a key. Doing so will result in undefined
* behaviour.
*/
public class IntObjMap
<V
> {
private static final int INIT_SIZE =
1 << 8;
private int size
;
private int[] keys
;
private V
[] values
;
private int capacity
;
private int targetSize
;
private final float loadFactor
;
private static final int OFF =
7;
public IntObjMap
() {
this(INIT_SIZE, 0.9f
);
}
public IntObjMap
(int initCap,
float load
) {
if (!Utils.
isPowerOfTwo(initCap
))
throw new IllegalArgumentException("The initial capacity " + initCap +
" must be a power of two");
keys =
new int[initCap
];
values =
(V
[]) new Object[initCap
];
capacity = initCap
;
loadFactor = load
;
targetSize =
(int) (initCap
* load
);
assert targetSize
> 0;
}
public int size
() {
return size
;
}
public V get
(int key
) {
int ind = keyPos
(key
);
if (keys
[ind
] ==
0)
return null;
return values
[ind
];
}
public V put
(int key, V value
) {
ensureSpace
();
int ind = keyPos
(key
);
keys
[ind
] = key
;
V old = values
[ind
];
if (old ==
null)
size++
;
values
[ind
] = value
;
return old
;
}
private void ensureSpace
() {
while (size +
1 >= targetSize
) {
int ncap = capacity
<< 1;
targetSize =
(int) (ncap
* loadFactor
);
int[] okey = keys
;
V
[] oval = values
;
size =
0;
keys =
new int[ncap
];
values =
(V
[]) new Object[ncap
];
capacity = ncap
;
for (int i =
0; i
< okey.
length; i++
) {
int k = okey
[i
];
if (k
!=
0)
put
(k, oval
[i
]);
}
}
assert size
< capacity
;
}
private int keyPos
(int key
) {
int k = key
& (capacity -
1);
int h1 = keys
[k
];
if (h1
!=
0 && h1
!= key
) {
for (int k2 = k+OFF
; ; k2+= OFF
) {
if (k2
>= capacity
)
k2 -= capacity
;
int fk = keys
[k2
];
if (fk ==
0 || fk == key
) {
return k2
;
}
}
}
return k
;
}
}