/*
* Copyright 2014-2017 Real Logic Ltd.
*
* 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 org.agrona.collections;
import org.junit.Assert;
import org.junit.Test;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.number.OrderingComparison.lessThan;
import static org.junit.Assert.assertThat;
public class Int2ObjectHashMapTest
{
private final Int2ObjectHashMap<String> intToObjectMap = new Int2ObjectHashMap<>();
@Test
public void shouldDoPutAndThenGet()
{
final String value = "Seven";
intToObjectMap.put(7, value);
assertThat(intToObjectMap.get(7), is(value));
}
@Test
public void shouldReplaceExistingValueForTheSameKey()
{
final int key = 7;
final String value = "Seven";
intToObjectMap.put(key, value);
final String newValue = "New Seven";
final String oldValue = intToObjectMap.put(key, newValue);
assertThat(intToObjectMap.get(key), is(newValue));
assertThat(oldValue, is(value));
assertThat(intToObjectMap.size(), is(1));
}
@Test
public void shouldGrowWhenThresholdExceeded()
{
final float loadFactor = 0.5f;
final Int2ObjectHashMap<String> map = new Int2ObjectHashMap<>(32, loadFactor);
for (int i = 0; i < 16; i++)
{
map.put(i, Integer.toString(i));
}
assertThat(map.resizeThreshold(), is(16));
assertThat(map.capacity(), is(32));
assertThat(map.size(), is(16));
map.put(16, "16");
assertThat(map.resizeThreshold(), is(32));
assertThat(map.capacity(), is(64));
assertThat(map.size(), is(17));
assertThat(map.get(16), equalTo("16"));
assertThat((double)loadFactor, closeTo(map.loadFactor(), 0.0f));
}
@Test
public void shouldHandleCollisionAndThenLinearProbe()
{
final float loadFactor = 0.5f;
final Int2ObjectHashMap<String> map = new Int2ObjectHashMap<>(32, loadFactor);
final int key = 7;
final String value = "Seven";
map.put(key, value);
final int collisionKey = key + map.capacity();
final String collisionValue = Integer.toString(collisionKey);
map.put(collisionKey, collisionValue);
assertThat(map.get(key), is(value));
assertThat(map.get(collisionKey), is(collisionValue));
assertThat((double)loadFactor, closeTo(map.loadFactor(), 0.0f));
}
@Test
public void shouldClearCollection()
{
for (int i = 0; i < 15; i++)
{
intToObjectMap.put(i, Integer.toString(i));
}
assertThat(intToObjectMap.size(), is(15));
assertThat(intToObjectMap.get(1), is("1"));
intToObjectMap.clear();
assertThat(intToObjectMap.size(), is(0));
Assert.assertNull(intToObjectMap.get(1));
}
@Test
public void shouldCompactCollection()
{
final int totalItems = 50;
for (int i = 0; i < totalItems; i++)
{
intToObjectMap.put(i, Integer.toString(i));
}
for (int i = 0, limit = totalItems - 4; i < limit; i++)
{
intToObjectMap.remove(i);
}
final int capacityBeforeCompaction = intToObjectMap.capacity();
intToObjectMap.compact();
assertThat(intToObjectMap.capacity(), lessThan(capacityBeforeCompaction));
}
@Test
public void shouldContainValue()
{
final int key = 7;
final String value = "Seven";
intToObjectMap.put(key, value);
Assert.assertTrue(intToObjectMap.containsValue(value));
Assert.assertFalse(intToObjectMap.containsValue("NoKey"));
}
@Test
public void shouldContainKey()
{
final int key = 7;
final String value = "Seven";
intToObjectMap.put(key, value);
Assert.assertTrue(intToObjectMap.containsKey(key));
Assert.assertFalse(intToObjectMap.containsKey(0));
}
@Test
public void shouldRemoveEntry()
{
final int key = 7;
final String value = "Seven";
intToObjectMap.put(key, value);
Assert.assertTrue(intToObjectMap.containsKey(key));
intToObjectMap.remove(key);
Assert.assertFalse(intToObjectMap.containsKey(key));
}
@Test
public void shouldRemoveEntryAndCompactCollisionChain()
{
final int key = 12;
final String value = "12";
intToObjectMap.put(key, value);
intToObjectMap.put(13, "13");
final int collisionKey = key + intToObjectMap.capacity();
final String collisionValue = Integer.toString(collisionKey);
intToObjectMap.put(collisionKey, collisionValue);
intToObjectMap.put(14, "14");
assertThat(intToObjectMap.remove(key), is(value));
}
@Test
public void shouldIterateValues()
{
final Collection<String> initialSet = new HashSet<>();
for (int i = 0; i < 11; i++)
{
final String value = Integer.toString(i);
intToObjectMap.put(i, value);
initialSet.add(value);
}
final Collection<String> copyToSet = new HashSet<>();
for (final String s : intToObjectMap.values())
{
copyToSet.add(s);
}
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateKeysGettingIntAsPrimitive()
{
final Collection<Integer> initialSet = new HashSet<>();
for (int i = 0; i < 11; i++)
{
final String value = Integer.toString(i);
intToObjectMap.put(i, value);
initialSet.add(i);
}
final Collection<Integer> copyToSet = new HashSet<>();
for (final Int2ObjectHashMap.KeyIterator iter = intToObjectMap.keySet().iterator(); iter.hasNext(); )
{
copyToSet.add(iter.nextInt());
}
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateKeys()
{
final Collection<Integer> initialSet = new HashSet<>();
for (int i = 0; i < 11; i++)
{
final String value = Integer.toString(i);
intToObjectMap.put(i, value);
initialSet.add(i);
}
assertIterateKeys(initialSet);
assertIterateKeys(initialSet);
assertIterateKeys(initialSet);
}
private void assertIterateKeys(final Collection<Integer> initialSet)
{
final Collection<Integer> copyToSet = new HashSet<>();
for (final Integer aInteger : intToObjectMap.keySet())
{
copyToSet.add(aInteger);
}
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateAndHandleRemove()
{
final Collection<Integer> initialSet = new HashSet<>();
final int count = 11;
for (int i = 0; i < count; i++)
{
final String value = Integer.toString(i);
intToObjectMap.put(i, value);
initialSet.add(i);
}
final Collection<Integer> copyOfSet = new HashSet<>();
int i = 0;
for (final Iterator<Integer> iter = intToObjectMap.keySet().iterator(); iter.hasNext(); )
{
final Integer item = iter.next();
if (i++ == 7)
{
iter.remove();
}
else
{
copyOfSet.add(item);
}
}
final int reducedSetSize = count - 1;
assertThat(initialSet.size(), is(count));
assertThat(intToObjectMap.size(), is(reducedSetSize));
assertThat(copyOfSet.size(), is(reducedSetSize));
}
@Test
public void shouldIterateEntries()
{
final int count = 11;
for (int i = 0; i < count; i++)
{
final String value = Integer.toString(i);
intToObjectMap.put(i, value);
}
iterateEntries();
iterateEntries();
iterateEntries();
final String testValue = "Wibble";
for (final Map.Entry<Integer, String> entry : intToObjectMap.entrySet())
{
assertThat(String.valueOf(entry.getKey()), equalTo(entry.getValue()));
if (entry.getKey() == 7)
{
entry.setValue(testValue);
}
}
assertThat(intToObjectMap.get(7), equalTo(testValue));
}
private void iterateEntries()
{
for (final Map.Entry<Integer, String> entry : intToObjectMap.entrySet())
{
assertThat(String.valueOf(entry.getKey()), equalTo(entry.getValue()));
}
}
@Test
public void shouldGenerateStringRepresentation()
{
final int[] testEntries = {3, 1, 19, 7, 11, 12, 7};
for (final int testEntry : testEntries)
{
intToObjectMap.put(testEntry, String.valueOf(testEntry));
}
final String mapAsAString = "{12=12, 11=11, 7=7, 3=3, 19=19, 1=1}";
assertThat(intToObjectMap.toString(), equalTo(mapAsAString));
}
@Test
public void shouldCopyConstructAndBeEqual()
{
final int[] testEntries = {3, 1, 19, 7, 11, 12, 7};
for (final int testEntry : testEntries)
{
intToObjectMap.put(testEntry, String.valueOf(testEntry));
}
final Int2ObjectHashMap<String> mapCopy = new Int2ObjectHashMap<>(intToObjectMap);
assertThat(mapCopy, is(intToObjectMap));
}
}