// Hash.java /** * Copyright (C) 2008 10gen Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mongodb.util; public final class Hash { /** Creates a hash for a string. * @param s String to hash * @return the hash code */ public static final int hashBackward( String s ) { int hash = 0; for ( int i = s.length()-1; i >= 0; i-- ) hash = hash * 31 + s.charAt( i ); return hash; } /** Creates a long hash for a string. * @param s the string to hash * @return the hash code */ public static final long hashBackwardLong( String s ) { long hash = 0; for ( int i = s.length()-1; i >= 0; i-- ) hash = hash * 63 + s.charAt( i ); return hash; } /** @unexpose */ static final long _longHashConstant = 4095; /** * 64-bit hash, using longs, in stead of ints, for less collisions, for when it matters. * Calls longHash( s , 0 , s.length() ) * @param s The String to hash. * @return the hash code */ public static final long longHash( String s ) { return longHash( s , 0 , s.length() ); } /** * 64-bit hash using longs, starting on index 'start' and including everything before 'end'. * @param s The string to hash. * @param start Where to start the hash. * @param end Where to end the hash. * @return the hash code */ public static final long longHash( String s , int start , int end ) { long hash = 0; for ( ; start < end; start++ ) hash = _longHashConstant * hash + s.charAt( start ); return hash; } /** * Same as longHash(String), using only lower-case values of letters. * Calls longhash( s , 0 , s.length() ). * @param s The string to Hash. * @return the hash code */ public static final long longLowerHash( String s ) { return longLowerHash( s , 0 , s.length() ); } /** * Long (64-bit) hash, lower-cased, from [start-end) * @param s The string to hash. * @param start where to start hashing. * @param end Where to stop hashing. * @return the hash code */ public static final long longLowerHash( String s , int start , int end ) { long hash = 0; for ( ; start < end; start++ ) hash = _longHashConstant * hash + Character.toLowerCase( s.charAt( start ) ); return hash; } /** * Long (64-bit) hash, lower-cased, from [start-end) * @param s The string to hash. * @param start where to start hashing. * @param end Where to stop hashing. * @return the hash code */ public static final long longLowerHash( String s , int start , int end , long hash ) { for ( ; start < end; start++ ) hash = _longHashConstant * hash + Character.toLowerCase( s.charAt( start ) ); return hash; } /** Adds the lower-case equivalent of a character to an existing hash code. * @param hash the existing hash code * @param c the character to add * @return the hash code */ public static final long longLowerHashAppend( long hash , char c ) { return hash * _longHashConstant + Character.toLowerCase( c ); } /** Adds a character to an existing hash code. * @param hash the existing hash code * @param c the character to add * @return the hash code */ public static final long longHashAppend( long hash , char c ) { return hash * _longHashConstant + c; } /** * This is an exact copy of the String <code>hashCode()</code> function, aside from the lowercasing. * @param s string to be hashed * @return the hash code */ public static final int lowerCaseHash( String s ) { int h = 0; final int len = s.length(); for ( int i = 0; i < len; i++ ) h = 31*h + Character.toLowerCase( s.charAt( i ) ); return h; } /** * Creates a hash code of a lowercase string from [start-end) * @param s string to be hashed * @param start the starting index * @param end the ending index * @return the hash code */ public static final int lowerCaseHash( String s , int start , int end ) { int h = 0; final int len = s.length(); for ( int i = start; i < len && i < end; i++ ) h = 31*h + Character.toLowerCase( s.charAt( i ) ); return h; } /** * Creates a hash code of a string from [start-end) * @param s string to be hashed * @param start the starting index * @param end the ending index * @return the hash code */ public static final int hashCode( CharSequence s , int start , int end ) { int h = 0; final int len = s.length(); for ( int i = start; i < len && i < end; i++ ) h = 31*h + s.charAt( i ); return h; } /** * Creates a hash code of a lowercase string with whitespace removed from [start-end) * @param s string to be hashed * @param start the starting index * @param end the ending index * @return the hash code */ public static final int nospaceLowerHash( String s , int start , int end ) { int h = 0; final int len = s.length(); for ( int i = start; i < len && i < end; i++ ) { char c = s.charAt( i ); if ( Character.isWhitespace( c ) ) continue; h = 31*h + Character.toLowerCase( c ); } return h; } /** * This is an exact copy of the String <code>hashCode()</code> function, aside from the lowercasing. * No, it's not. It also ignores consecutive whitespace. * @param s string to be hashed * @return the hash code */ public static final int lowerCaseSpaceTrimHash( String s ) { int h = 0; int len = s.length(); while ( len > 1 && Character.isWhitespace( s.charAt( len-1 ) ) ) len--; boolean lastWasSpace = true; for ( int i = 0; i < len; i++ ) { boolean isSpace = Character.isWhitespace( s.charAt( i ) ); if ( isSpace && lastWasSpace ) continue; lastWasSpace = isSpace; h = 31*h + Character.toLowerCase( s.charAt( i ) ); } return h; } /** * Creates a hash code of a lowercase string from [start-end) ignoring whitespace * @param s string to be hashed * @param start the starting index * @param end the ending index * @return the hash code */ public static final int lowerCaseSpaceTrimHash( String s , int start , int end ) { int h = 0; int len = s.length(); while ( len > 1 && Character.isWhitespace( s.charAt( len-1 ) ) ) len--; boolean lastWasSpace = true; for ( int i = start; i < len && i < end; i++ ) { boolean isSpace = Character.isWhitespace( s.charAt( i ) ); if ( isSpace && lastWasSpace ) continue; lastWasSpace = isSpace; h = 31*h + Character.toLowerCase( s.charAt( i ) ); } return h; } /** * Calculate the hashcode for a series of strings combined as one. * @param strings Varargs array of Strings. * @return A hashcode. */ public static final int hashCode( String ... strings ) { int h = 0; for ( String s : strings ) { int len = s.length(); for ( int i = 0; i < len; i++ ) h = 31*h + s.charAt( i ); } return h; } }