/** * Returns the long associated with the String or 0 if there is no long associated with the * string. If newValue is not equal to 0 then this becomes the new value associated with the * string. * * @param str the String. * @param newValue if not equal to 0, the new value to be associated with the string. * @return the long currently associated with the String or 0 if there is no long associated with * the string. * @throws IOException if an I/O error occurs or the hash table is full. */ public long getAndPut(String str, long newValue) throws IOException { if (str == null) { throw new IllegalArgumentException("str is null"); } if (newValue == 0) { Long l = cache.get(str); if (l != null) { return l.longValue(); } } int hashCode = str.hashCode(); int startBucket = calcBucket(hashCode); int bucket = startBucket; long value; // Try buckets until we find the correct string or an empty bucket. while ((value = getValue(bucket)) != 0) { // Check the hash code. long offset = (long) bucket * 4; if (hashCode == hashFile.getInt(offset)) { // Fetch the string and compare with the target string. String bucketStr = readString(hashFile.getUInt(offset + 1)); if (str.equals(bucketStr)) { if (newValue != 0) { hashFile.putLong((long) bucket * 2 + 1, newValue); // Add the new value to the cache. cache.put(str, newValue); } else { // Add the value to the cache. cache.put(str, value); } return value; } } // Try the next bucket. bucket = (bucket + 1) % nrBuckets; if (bucket == startBucket) { throw new IOException("Hash table full"); } } if (newValue != 0) { // Add the new value to the cache. cache.put(str, newValue); // Add a new hash bucket. long bucketOffset = (long) bucket * 4; hashFile.putInt(bucketOffset, hashCode); hashFile.putUInt(bucketOffset + 1, writeString(str)); hashFile.putLong((long) bucket * 2 + 1, newValue); ++nrUsedBuckets; if (nrUsedBuckets >= (int) (nrBuckets * REHASH_LIMIT)) { rehash(findPrime(nrBuckets)); } } return 0; }