/*
* Copyright 2015 Goldman Sachs.
*
* 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.gs.collections.impl.map.mutable.primitive;
import java.util.Random;
import com.gs.collections.api.list.primitive.MutableIntList;
import com.gs.collections.api.map.primitive.MutableIntLongMap;
import com.gs.collections.api.set.primitive.MutableIntSet;
import com.gs.collections.impl.SpreadFunctions;
import com.gs.collections.impl.list.mutable.primitive.IntArrayList;
import com.gs.collections.impl.set.mutable.primitive.IntHashSet;
import org.junit.Assert;
import org.junit.Test;
public class IntLongMapProbeTest
{
private static final int SMALL_COLLIDING_KEY_COUNT = 500;
private static final int LARGE_COLLIDING_KEY_COUNT = 40000;
private int smallMask(int spread)
{
return spread & ((1 << 11) - 1);
}
private int largeMask(int spread)
{
return spread & ((1 << 20) - 1);
}
@Test
public void randomNumbers_get()
{
MutableIntLongMap intlongSmallNonPresized = new IntLongHashMap();
this.testRandomGet(intlongSmallNonPresized, SMALL_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongSmallPresized = new IntLongHashMap(1_000);
this.testRandomGet(intlongSmallPresized, SMALL_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongLargeNonPresized = new IntLongHashMap();
this.testRandomGet(intlongLargeNonPresized, LARGE_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongLargePresized = new IntLongHashMap(1_000_000);
this.testRandomGet(intlongLargePresized, LARGE_COLLIDING_KEY_COUNT);
}
@Test
public void nonRandomNumbers_get()
{
MutableIntLongMap intlongMapSmall = new IntLongHashMap(1_000);
int[] intKeysForSmallMap = this.getSmallCollidingNumbers().toArray();
this.testNonRandomGet(intlongMapSmall, SMALL_COLLIDING_KEY_COUNT, intKeysForSmallMap);
MutableIntLongMap intlongMapLarge = new IntLongHashMap(1_000_000);
int[] intKeysForLargeMap = this.getLargeCollidingNumbers().toArray();
this.testNonRandomGet(intlongMapLarge, LARGE_COLLIDING_KEY_COUNT, intKeysForLargeMap);
}
@Test
public void nonRandomNumbers_remove()
{
MutableIntLongMap intlongMapSmallNonPresized = new IntLongHashMap();
int[] intKeysForMap = this.getSmallCollidingNumbers().toArray();
this.testNonRandomRemove(intlongMapSmallNonPresized, SMALL_COLLIDING_KEY_COUNT, intKeysForMap);
MutableIntLongMap intlongMapSmallPresized = new IntLongHashMap(1_000);
int[] intKeysForMap2 = this.getSmallCollidingNumbers().toArray();
this.testNonRandomRemove(intlongMapSmallPresized, SMALL_COLLIDING_KEY_COUNT, intKeysForMap2);
MutableIntLongMap intlongMapLargeNonPresized = new IntLongHashMap();
int[] intKeysForMap3 = this.getLargeCollidingNumbers().toArray();
this.testNonRandomRemove(intlongMapLargeNonPresized, LARGE_COLLIDING_KEY_COUNT, intKeysForMap3);
MutableIntLongMap intlongMapLargePresized = new IntLongHashMap(1_000_000);
int[] intKeysForMap4 = this.getLargeCollidingNumbers().toArray();
this.testNonRandomRemove(intlongMapLargePresized, LARGE_COLLIDING_KEY_COUNT, intKeysForMap4);
}
@Test
public void randomNumbers_remove()
{
MutableIntLongMap intlongMapSmallNonPresized = new IntLongHashMap();
this.testRandomRemove(intlongMapSmallNonPresized, SMALL_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongMapSmallPresized = new IntLongHashMap(1_000);
this.testRandomRemove(intlongMapSmallPresized, SMALL_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongMapLargeNonPresized = new IntLongHashMap();
this.testRandomRemove(intlongMapLargeNonPresized, LARGE_COLLIDING_KEY_COUNT);
MutableIntLongMap intlongMapLargePresized = new IntLongHashMap(1_000_000);
this.testRandomRemove(intlongMapLargePresized, LARGE_COLLIDING_KEY_COUNT);
}
private void testNonRandomGet(MutableIntLongMap intlongMap, int keyCount, int[] intKeysForMap)
{
Random random = new Random(0x123456789ABCDL);
this.shuffle(intKeysForMap, random);
for (int i = 0; i < keyCount; i++)
{
intlongMap.put(intKeysForMap[i], (long) (intKeysForMap[i] * 10));
}
for (int i = 0; i < intlongMap.size(); i++)
{
Assert.assertEquals((long) (intKeysForMap[i] * 10), intlongMap.get(intKeysForMap[i]));
}
}
private void testRandomGet(MutableIntLongMap intlongMap, int keyCount)
{
Random random = new Random(0x123456789ABCDL);
MutableIntSet set = new IntHashSet(keyCount);
while (set.size() < keyCount)
{
set.add(random.nextInt());
}
int[] randomNumbersForMap = set.toArray();
this.shuffle(randomNumbersForMap, random);
for (int i = 0; i < keyCount; i++)
{
intlongMap.put(randomNumbersForMap[i], (long) (randomNumbersForMap[i] * 10));
}
for (int i = 0; i < intlongMap.size(); i++)
{
Assert.assertEquals((long) (randomNumbersForMap[i] * 10), intlongMap.get(randomNumbersForMap[i]));
}
}
private void testNonRandomRemove(MutableIntLongMap intlongMap, int keyCount, int[] intKeysForMap)
{
Random random = new Random(0x123456789ABCDL);
this.shuffle(intKeysForMap, random);
for (int i = 0; i < keyCount; i++)
{
intlongMap.put(intKeysForMap[i], (long) (intKeysForMap[i] * 10));
}
this.shuffle(intKeysForMap, random);
for (int i = 0; i < intKeysForMap.length; i++)
{
intlongMap.remove(intKeysForMap[i]);
for (int j = i + 1; j < intKeysForMap.length; j++)
{
Assert.assertEquals((long) (intKeysForMap[j] * 10), intlongMap.get(intKeysForMap[j]));
}
}
}
private void testRandomRemove(MutableIntLongMap intlongMap, int keyCount)
{
Random random = new Random(0x123456789ABCDL);
MutableIntSet set = new IntHashSet(keyCount);
while (set.size() < keyCount)
{
set.add(random.nextInt());
}
int[] intKeysForMap = set.toArray();
this.shuffle(intKeysForMap, random);
for (int i = 0; i < keyCount; i++)
{
intlongMap.put(intKeysForMap[i], (long) (intKeysForMap[i] * 10));
}
this.shuffle(intKeysForMap, random);
for (int i = 0; i < intKeysForMap.length; i++)
{
intlongMap.remove(intKeysForMap[i]);
for (int j = i + 1; j < intKeysForMap.length; j++)
{
Assert.assertEquals((long) (intKeysForMap[j] * 10), intlongMap.get(intKeysForMap[j]));
}
}
}
private MutableIntList getSmallCollidingNumbers()
{
int lower = Integer.MIN_VALUE;
int upper = Integer.MAX_VALUE;
MutableIntList collidingNumbers = new IntArrayList();
int numberOne = this.smallMask(SpreadFunctions.intSpreadOne(0xABCDEF1));
int numberTwo = this.smallMask(SpreadFunctions.intSpreadTwo(0xABCDEF1));
for (int i = lower; i < upper && collidingNumbers.size() < SMALL_COLLIDING_KEY_COUNT; i++)
{
if (this.smallMask(SpreadFunctions.intSpreadOne(i)) == numberOne && this.smallMask(SpreadFunctions.intSpreadTwo(i)) == numberTwo)
{
collidingNumbers.add(i);
}
}
return collidingNumbers;
}
private MutableIntList getLargeCollidingNumbers()
{
int lower = Integer.MIN_VALUE;
int upper = Integer.MAX_VALUE;
int number = 23;
MutableIntList collidingNumbers = new IntArrayList();
for (int i = lower; i < upper && collidingNumbers.size() < LARGE_COLLIDING_KEY_COUNT; i++)
{
int index = this.largeMask(SpreadFunctions.intSpreadOne(i));
if (index >= number && index <= number + 100)
{
collidingNumbers.add(i);
}
}
return collidingNumbers;
}
public void shuffle(int[] intArray, Random rnd)
{
for (int i = intArray.length; i > 1; i--)
{
IntLongMapProbeTest.swap(intArray, i - 1, rnd.nextInt(i));
}
}
private static void swap(int[] arr, int i, int j)
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}