From 7cb9b846037b9ef00dbd988a3fa5b4f03de4d012 Mon Sep 17 00:00:00 2001 From: YuriiZaripa <0939864774z@gmail.com> Date: Wed, 23 Aug 2023 17:16:55 +0300 Subject: [PATCH 1/2] init --- .../opensource/longmap/LongMapImpl.java | 183 +++++++++++++++++- .../opensource/longmap/LongMapImplTest.java | 178 +++++++++++++++++ 2 files changed, 356 insertions(+), 5 deletions(-) create mode 100644 src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java diff --git a/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java b/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java index 2f0b54b..d6224d1 100644 --- a/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java +++ b/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java @@ -1,43 +1,216 @@ package de.comparus.opensource.longmap; +import java.util.Arrays; + public class LongMapImpl implements LongMap { + + private static final int DEFAULT_CAPACITY = 16; + private static final float DEFAULT_LOAD_FACTOR = 0.75f; + private static final int DEFAULT_INCREASE_CAPACITY = 2; + + private int size; + private int capacity; + private int threshold; + private Node[] table; + + private static class Node { + + private final long key; + private V value; + private Node next; + + public Node(long key, V value) { + this.key = key; + this.value = value; + } + + public boolean hasNext() { + return next != null; + } + } + + public LongMapImpl() { + this.capacity = DEFAULT_CAPACITY; + this.table = new Node[DEFAULT_CAPACITY]; + this.threshold = (int) (capacity * DEFAULT_LOAD_FACTOR); + } + public V put(long key, V value) { - return null; + if (threshold < size) { + resize(); + } + int index = Long.hashCode(key) & (capacity - 1); + + if (table[index] == null) { + table[index] = new Node(key, value); + size++; + + return value; + } + + Node currentNode = table[index]; + while (currentNode.hasNext() || currentNode.key == key) { + if (currentNode.key == key) { + currentNode.value = value; + + return value; + } + + currentNode = currentNode.next; + } + currentNode.next = new Node<>(key, value); + size++; + + return value; } public V get(long key) { + if (isEmpty()) { + return null; + } + int index = Long.hashCode(key) & (capacity - 1); + Node currentNode = table[index]; + + while (currentNode != null) { + if (currentNode.key == key) { + return currentNode.value; + } + + currentNode = currentNode.next; + } + return null; } public V remove(long key) { + int index = Long.hashCode(key) & (capacity - 1); + if (isEmpty() || table[index] == null) { + return null; + } + Node currentNode = table[index]; + + if (currentNode.key == key) { + table[index] = currentNode.next; + size--; + + return currentNode.value; + } + + while (currentNode.hasNext()) { + if (currentNode.next.key == key) { + V removed = currentNode.next.value; + currentNode.next = currentNode.next.next; + size--; + + return removed; + } + + currentNode = currentNode.next; + } + return null; } public boolean isEmpty() { - return false; + return size == 0; } public boolean containsKey(long key) { + if (isEmpty()) { + return false; + } + int index = Long.hashCode(key) & (capacity - 1); + Node currentNode = table[index]; + + while (currentNode != null) { + if (currentNode.key == key) { + return true; + } + + currentNode = currentNode.next; + } + return false; } public boolean containsValue(V value) { + if (isEmpty()) { + return false; + } + + for (Node currentNode : table) { + while (currentNode != null) { + if (currentNode.value != null && currentNode.value.equals(value)) { + return true; + } + + currentNode = currentNode.next; + } + } + return false; } public long[] keys() { - return null; + if (isEmpty()) { + return new long[0]; + } + long[] keys = new long[size]; + int index = 0; + + for (Node currentNode : table) { + while (currentNode != null) { + keys[index++] = currentNode.key; + + currentNode = currentNode.next; + } + } + + return keys; } public V[] values() { - return null; + if (isEmpty()) { + return (V[]) new Object[0]; + } + V[] values = (V[]) new Object[size]; + int index = 0; + + for (Node currentNode : table) { + while (currentNode != null) { + values[index++] = currentNode.value; + + currentNode = currentNode.next; + } + } + + return values; } public long size() { - return 0; + return size; } public void clear() { + if (table != null && size > 0) { + size = 0; + Arrays.fill(table, null); + } + } + + private void resize() { + Node[] oldTable = table; + table = new Node[table.length * DEFAULT_INCREASE_CAPACITY]; + capacity = table.length; + size = 0; + threshold = (int) (oldTable.length * DEFAULT_LOAD_FACTOR); + + for (Node currantNode : oldTable) { + while (currantNode != null) { + put(currantNode.key, currantNode.value); + currantNode = currantNode.next; + } + } } } diff --git a/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java b/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java new file mode 100644 index 0000000..43d87dd --- /dev/null +++ b/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java @@ -0,0 +1,178 @@ +package de.comparus.opensource.longmap; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class LongMapImplTest { + + @Test + public void testPut_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertEquals("First", map.put(1, "First")); + assertEquals("Second", map.put(2, "Second")); + } + + @Test + public void testGet_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(1, "First"); + map.put(2, "Second"); + + assertEquals("First", map.get(1)); + assertEquals("Second", map.get(2)); + } + + @Test + public void testGet_fromEmptyMap_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertNull(map.get(1)); + } + + @Test + public void testGet_byNotExistingKey_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(1, "First"); + map.put(2, "Second"); + + assertNull(map.get(3)); + } + + @Test + public void testRemove_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertEquals("Zero", map.remove(0)); + assertEquals("First", map.remove(1)); + } + + @Test + public void testRemove_fromEmptyMap_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertNull(map.remove(0)); + } + + @Test + public void testRemove_byNotExistingKey_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertNull(map.get(3)); + } + + @Test + public void testIsEmpty_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertFalse(map.isEmpty()); + } + + @Test + public void testIsEmpty_fromEmptyMap_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertTrue(map.isEmpty()); + } + + @Test + public void testContainsKey_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertTrue(map.containsKey(0)); + } + + @Test + public void testContainsKey_byNotExistingKey_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertFalse(map.containsKey(2)); + } + + @Test + public void testContainsValue_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertTrue(map.containsValue("Zero")); + } + + @Test + public void testContainsValue_byNotExistingValue_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertFalse(map.containsValue("Second")); + } + + @Test + public void testKeys_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertArrayEquals(new long[]{0L, 1L}, map.keys()); + } + + @Test + public void testKeys_fromEmptyMap_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertArrayEquals(new long[0], map.keys()); + } + + @Test + public void testValues_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertArrayEquals(new String[]{"Zero", "First"}, map.values()); + } + + @Test + public void testValues_fromEmptyMap_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + + assertArrayEquals(new String[0], map.values()); + } + + @Test + public void testSize_regularUsing_shouldSuccess() { + LongMap emptyMap = new LongMapImpl<>(); + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + assertEquals(0, emptyMap.size()); + assertEquals(2, map.size()); + } + + @Test + public void testClear_regularUsing_shouldSuccess() { + LongMap map = new LongMapImpl<>(); + map.put(0, "Zero"); + map.put(1, "First"); + + map.clear(); + assertEquals(0, map.size()); + assertArrayEquals(new long[0], map.keys()); + } +} From 2f5d674d966bd376ddfead9e6635db6e4e9d6ec5 Mon Sep 17 00:00:00 2001 From: YuriiZaripa <0939864774z@gmail.com> Date: Thu, 24 Aug 2023 12:24:30 +0300 Subject: [PATCH 2/2] init --- .../opensource/longmap/LongMapImpl.java | 12 ++++-- .../opensource/longmap/LongMapImplTest.java | 38 +++++++++---------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java b/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java index d6224d1..e0a7360 100644 --- a/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java +++ b/src/main/java/de/comparus/opensource/longmap/LongMapImpl.java @@ -39,7 +39,7 @@ public V put(long key, V value) { if (threshold < size) { resize(); } - int index = Long.hashCode(key) & (capacity - 1); + int index = indexCalculation(key); if (table[index] == null) { table[index] = new Node(key, value); @@ -68,7 +68,7 @@ public V get(long key) { if (isEmpty()) { return null; } - int index = Long.hashCode(key) & (capacity - 1); + int index = indexCalculation(key); Node currentNode = table[index]; while (currentNode != null) { @@ -83,7 +83,7 @@ public V get(long key) { } public V remove(long key) { - int index = Long.hashCode(key) & (capacity - 1); + int index = indexCalculation(key); if (isEmpty() || table[index] == null) { return null; } @@ -119,7 +119,7 @@ public boolean containsKey(long key) { if (isEmpty()) { return false; } - int index = Long.hashCode(key) & (capacity - 1); + int index = indexCalculation(key); Node currentNode = table[index]; while (currentNode != null) { @@ -198,6 +198,10 @@ public void clear() { } } + private int indexCalculation(long key) { + return Long.hashCode(key) & (capacity - 1); + } + private void resize() { Node[] oldTable = table; table = new Node[table.length * DEFAULT_INCREASE_CAPACITY]; diff --git a/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java b/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java index 43d87dd..306379a 100644 --- a/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java +++ b/src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java @@ -11,7 +11,7 @@ public class LongMapImplTest { @Test - public void testPut_regularUsing_shouldSuccess() { + public void put_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); assertEquals("First", map.put(1, "First")); @@ -19,7 +19,7 @@ public void testPut_regularUsing_shouldSuccess() { } @Test - public void testGet_regularUsing_shouldSuccess() { + public void get_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(1, "First"); map.put(2, "Second"); @@ -29,14 +29,14 @@ public void testGet_regularUsing_shouldSuccess() { } @Test - public void testGet_fromEmptyMap_shouldSuccess() { + public void get_fromEmptyMap_shouldReturnNull() { LongMap map = new LongMapImpl<>(); assertNull(map.get(1)); } @Test - public void testGet_byNotExistingKey_shouldSuccess() { + public void get_byNotExistingKey_shouldReturnNull() { LongMap map = new LongMapImpl<>(); map.put(1, "First"); map.put(2, "Second"); @@ -45,7 +45,7 @@ public void testGet_byNotExistingKey_shouldSuccess() { } @Test - public void testRemove_regularUsing_shouldSuccess() { + public void remove_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -55,14 +55,14 @@ public void testRemove_regularUsing_shouldSuccess() { } @Test - public void testRemove_fromEmptyMap_shouldSuccess() { + public void remove_fromEmptyMap_shouldReturnNull() { LongMap map = new LongMapImpl<>(); assertNull(map.remove(0)); } @Test - public void testRemove_byNotExistingKey_shouldSuccess() { + public void remove_byNotExistingKey_shouldReturnNull() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -71,7 +71,7 @@ public void testRemove_byNotExistingKey_shouldSuccess() { } @Test - public void testIsEmpty_regularUsing_shouldSuccess() { + public void isEmpty_positiveScenario_shouldReturnFalse() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -80,14 +80,14 @@ public void testIsEmpty_regularUsing_shouldSuccess() { } @Test - public void testIsEmpty_fromEmptyMap_shouldSuccess() { + public void isEmpty_fromEmptyMap_shouldReturnTrue() { LongMap map = new LongMapImpl<>(); assertTrue(map.isEmpty()); } @Test - public void testContainsKey_regularUsing_shouldSuccess() { + public void containsKey_positiveScenario_shouldReturnTrue() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -96,7 +96,7 @@ public void testContainsKey_regularUsing_shouldSuccess() { } @Test - public void testContainsKey_byNotExistingKey_shouldSuccess() { + public void containsKey_byNotExistingKey_shouldReturnFalse() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -105,7 +105,7 @@ public void testContainsKey_byNotExistingKey_shouldSuccess() { } @Test - public void testContainsValue_regularUsing_shouldSuccess() { + public void containsValue_positiveScenario_shouldReturnTrue() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -114,7 +114,7 @@ public void testContainsValue_regularUsing_shouldSuccess() { } @Test - public void testContainsValue_byNotExistingValue_shouldSuccess() { + public void containsValue_byNotExistingValue_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -123,7 +123,7 @@ public void testContainsValue_byNotExistingValue_shouldSuccess() { } @Test - public void testKeys_regularUsing_shouldSuccess() { + public void keys_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -132,14 +132,14 @@ public void testKeys_regularUsing_shouldSuccess() { } @Test - public void testKeys_fromEmptyMap_shouldSuccess() { + public void keys_fromEmptyMap_shouldReturnEmptyArray() { LongMap map = new LongMapImpl<>(); assertArrayEquals(new long[0], map.keys()); } @Test - public void testValues_regularUsing_shouldSuccess() { + public void values_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First"); @@ -148,14 +148,14 @@ public void testValues_regularUsing_shouldSuccess() { } @Test - public void testValues_fromEmptyMap_shouldSuccess() { + public void values_fromEmptyMap_shouldReturnEmptyArray() { LongMap map = new LongMapImpl<>(); assertArrayEquals(new String[0], map.values()); } @Test - public void testSize_regularUsing_shouldSuccess() { + public void size_positiveScenario_shouldSuccess() { LongMap emptyMap = new LongMapImpl<>(); LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); @@ -166,7 +166,7 @@ public void testSize_regularUsing_shouldSuccess() { } @Test - public void testClear_regularUsing_shouldSuccess() { + public void clear_positiveScenario_shouldSuccess() { LongMap map = new LongMapImpl<>(); map.put(0, "Zero"); map.put(1, "First");