public String reuse(final String value) {
		if (value == null) {
			return null;
		}
		final int hash = value.hashCode();
		/*
		 *  we use a special masking routine here. This is important.
		 *  we always do a 16-bit shift, XOR it with the unshifted value, and
		 *  then apply the mask.
		 *  The reason is relatively simple: it makes rehashing much faster
		 *  because you never need to shift values in the rehash, they are always
		 *  just appended.
		 *  Further, there is no real need to get a true random distribution in
		 *  the buckets... it's not important. The String.hashCode() is a good
		 *  enough hash function so we do not lose much by doing it this way.
		 *  
		 *  In detail:
		 *  Normally for a bucketing/hashing system we will try to use as many
		 *  bits as possible to create the bucket hash for the value. In this
		 *  case though, we XOR the high 16 bits with the low 16 bits (and keep
		 *  the high 16 bits unchanged. Lets call this the 'interim result'.
		 *  We then apply our bit mask to that interim result to get the bucket
		 *  id. The important thing here is that the interim result is the same
		 *  no matter how many buckets there are.
		 *  
		 *  If we need to rehash the buckets, the mask will include more bits,
		 *  and that guarantees that the values in any one 'original' bucket
		 *  will be divided in to different buckets, and never merged with
		 *  values from a different original bucket.
		 *  
		 *  Thus, in a rehash, both because of the way we calculate the bucketid
		 *  and also because the values in a bucket are stored in increasing
		 *  hash value order, we never need to insert a value in to the middle
		 *  of the rehashed bucket, we can always add to the end.
		 */
		final int bucketid = ((hash >>> 16) ^ hash) & mask;
		
		final int length = lengths[bucketid];
		if (length == 0) {
			// start a new bucket
			final String v = compact(value);
			buckets[bucketid] = new String[GROW];
			buckets[bucketid][0] = v;
			lengths[bucketid] = 1;
			return v;
		}
		
		// get the existing bucket.
		String[] bucket = buckets[bucketid];
		
		// note the final value calculated as -val - 1
		final int ip = - locate(hash, value, bucket, length) - 1;
		if (ip < 0) {
			// this means we have found the value.
			return bucket[- ip - 1];
		}
		if (length >= MAXBUCKET) {
			// need to rehash, so we do, and then add our value
			rehash();
			return reuse(value);
		}
		if (length == bucket.length) {
			// there is no space for our value.
			bucket = ArrayCopy.copyOf(bucket, length + GROW);
			buckets[bucketid] = bucket;
		}
		System.arraycopy(bucket, ip, bucket, ip + 1, length - ip);
		final String v = compact(value);
		bucket[ip] = v;
		lengths[bucketid]++;
		return v;
	}