CharSequenceHashBuilder { GeneratedHashRules perfectCharSequenceHashBuilder(final CharSequence[] values) { final int mixBits = 0; int sigBits = 1; int maxValueLen = 0; int m = values.length; while (--m>=0) { if (values[m].length()>maxValueLen) { maxValueLen = values[m].length(); } } maxValueLen = maxValueLen<<sigBits; int[] charLenCountSpace = new int[maxValueLen+1]; int[] charLenCountGroups = new int[maxValueLen]; boolean isDone = false; byte bitShift = 0; int shiftsStackAsBits = 0; shiftStackDepth = 0; boolean needsMoreSplitting = true; int lastGroupSize = Integer.MAX_VALUE; do { if (bitShift>=0) { Arrays.fill(largestGroup, 0); needsMoreSplitting = recursiveBalanceScan(values, shiftsStack, shiftStackDepth, 0, shiftsStackAsBits, charHashSeed, -1, -1, 0, largestGroup, lengthCountSpace, mixBits, sigBits); bitShift = (byte)findIdxOfSmallestGroup(largestGroup, (lastGroupSize>>1)+1, shiftsStackAsBits); if (bitShift>=0) { int groupSize = largestGroup[bitShift]; int newBit = 1<<bitShift; if ((shiftsStackAsBits & newBit) != 0) { System.err.println("picked same bit twice"); lastGroupSize = Integer.MAX_VALUE; bitShift = -1; } else { shiftsStackAsBits |= newBit; shiftsStack[shiftStackDepth++] = bitShift; } lastGroupSize=groupSize; } else { lastGroupSize = Integer.MAX_VALUE; } } else { Arrays.fill(charLenCountGroups, 0); needsMoreSplitting = recursiveBalanceScan(values, shiftsStack, shiftStackDepth, 0, shiftsStackAsBits, charHashSeed, charHashSeedDepth, charHashSeedDepth, 0, charLenCountGroups, charLenCountSpace, mixBits, sigBits); int seedIdx = findIdxOfSmallestGroup(charLenCountGroups, lastGroupSize,0); if (seedIdx>=0) { int groupSize = charLenCountGroups[seedIdx]; charHashSeed[charHashSeedDepth++] = seedIdx; lastGroupSize = groupSize; if (1==groupSize) { needsMoreSplitting = false; break; } } else { break; } } } while (true); return new GeneratedHashRules(needsMoreSplitting, shiftsStackAsBits, shiftsStack, shiftStackDepth, charHashSeed, charHashSeedDepth); } CharSequenceHashBuilder();   }
@Test public void simpleTextTest() { CharSequence[] testValues = new CharSequence[] { "a", "ab", "abc", "abcd", "abcde", "abcdef", "abcdefg", "abcdefgh", "abcdefgc", "abcdefgq", "abcdefgai", "abcdefgbij", }; CharSequenceHashBuilder obj = new CharSequenceHashBuilder(); GeneratedHashRules result = obj.perfectCharSequenceHashBuilder(testValues); assertEquals(false, result.needsMoreSplitting()); assertEquals(0xF, result.lengthMask()); }