Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/de/comparus/opensource/longmap/LongMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

public interface LongMap<V> {
V put(long key, V value);

V get(long key);

V remove(long key);

boolean isEmpty();

boolean containsKey(long key);

boolean containsValue(V value);

long[] keys();

V[] values();

long size();

void clear();
}
161 changes: 155 additions & 6 deletions src/main/java/de/comparus/opensource/longmap/LongMapImpl.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,192 @@
package de.comparus.opensource.longmap;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class LongMapImpl<V> implements LongMap<V> {
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private static final int DEFAULT_RESIZE_MULTIPLIER = 2;
private int size;
private int threshold;
private Node<Long, V>[] table;

public LongMapImpl() {
threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
table = new Node[DEFAULT_INITIAL_CAPACITY];
size = 0;
}

public V put(long key, V value) {
return null;
if (size >= threshold) {
resize();
}
int index = getIndex(key);
Node<Long,V> newNode = new Node<>(key, value);
if (table[index] == null) {
table[index] = newNode;
} else {
Node currentNode = table[index];
while (currentNode != null) {
if (Objects.equals(key, currentNode.key)) {
currentNode.value = value;
return value;
}
if (currentNode.next == null) {
currentNode.next = newNode;
break;
}
currentNode = currentNode.next;
}
}
size++;
return value;
}

public V get(long key) {
int index = getIndex(key);
Node<Long, V> node = table[index];
while (node != null) {
if (Objects.equals(key, node.key)) {
return node.value;
}
node = node.next;
}
return null;
}

public V remove(long key) {
return null;
int index = getIndex(key);
if (table[index] == null) {
return null;
}
int counter = 0;
Node<Long, V> node = table[index];
while (node != null) {
if (node.key.equals(key)) {
break;
}
counter++;
node = node.next;
}
V value = null;
if (counter == 0) {
value = table[index].value;
table[index] = table[index].next;
} else {
node = table[index];
for (int i = 0; i < counter - 1; i++) {
node = node.next;
}
value = node.next.value;
node.next = node.next.next;
}
size--;
return value;
}

public boolean isEmpty() {
return false;
return size == 0;
}

public boolean containsKey(long key) {
int index = getIndex(key);
Node<Long, V> node = table[index];
while (node != null) {
if (node.key.equals(key)) {
return true;
}
node = node.next;
}
return false;
}

public boolean containsValue(V value) {
for (int i = 0; i < table.length; i++) {
Node<Long, V> node = table[i];
while (node != null) {
if (node.value.equals(value)) {
return true;
}
node = node.next;
}
}
return false;
}

public long[] keys() {
return null;
long[] result = new long[(int)size()];
int index = 0;
for (int i = 0; i < table.length; i++) {
Node<Long, V> node = table[i];
while (node != null) {
result[index] = node.key;
index++;
node = node.next;
}
}
return result;
}

public V[] values() {
return null;
List<V> list = new ArrayList<>();
for (int i = 0; i < table.length; i++) {
Node<Long, V> node = table[i];
while (node != null) {
list.add(node.value);
node = node.next;
}
}
V[] result = (V[]) java.lang.reflect.Array.newInstance(list.get(0)
.getClass(), list.size());
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}

public long size() {
return 0;
return size;
}

public void clear() {
if (table != null && size > 0) {
size = 0;
for (int i = 0; i < table.length; ++i) {
table[i] = null;
}
}
System.gc();
}

private int getIndex(Long key) {
return (key == null) ? 0 : Math.abs(Objects.hash(key) % table.length);
}

private void resize() {
Node<Long,V>[] oldTable = table;
int newCapacity = oldTable.length * DEFAULT_RESIZE_MULTIPLIER;
threshold = (int) (newCapacity * DEFAULT_LOAD_FACTOR);
table = new Node[newCapacity];
size = 0;
for (Node<Long, V> node : oldTable) {
while (node != null) {
put(node.key, node.value);
node = node.next;
}
}
}

private static class Node<L, V> {
private final Long key;
private V value;
private Node<L, V> next;

private Node(Long key, V value) {
this.key = key;
this.value = value;
this.next = null;
}
}
}
137 changes: 137 additions & 0 deletions src/test/java/de/comparus/opensource/longmap/LongMapImplTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package de.comparus.opensource.longmap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LongMapImplTest {
private LongMap<String> map;

@Before
public void initializeMap() {
map = new LongMapImpl<>();
}

@After
public void destroyMap() {
System.gc();
}

@Test
public void put_validBehavior_ok() {
String expected = "first value";
String actual = map.put(1L, expected);
assertEquals(expected, actual);
}

@Test
public void put_collision_ok() {
String expected = "third value";
map.put(1L, "first value");
map.put(17L, "second value");
String actual = map.put(33L, expected);
assertEquals(expected, actual);
}

@Test
public void get_validBehavior_ok() {
String expected = "first value";
map.put(1, expected);
String actual = map.get(1L);
assertEquals(expected, actual);
}

@Test
public void get_invalidBehavior_notOk() {
assertNull(map.get(1L));
}

@Test
public void remove_validBehavior_ok() {
map.put(1L, "first value");
assertNotNull(map.remove(1L));
}

@Test
public void remove_invalidBehavior_notOk() {
assertNull(map.remove(1L));
}

@Test
public void isEmpty_validBehavior_ok() {
assertTrue(map.isEmpty());
}

@Test
public void isEmpty_invalidBehavior_notOk() {
map.put(1L, "first value");
assertFalse(map.isEmpty());
}

@Test
public void containsKey_validBehavior_ok() {
map.put(1, "first value");
assertTrue(map.containsKey(1L));
}

@Test
public void containsKey_invalidBehavior_notOk() {
assertFalse(map.containsKey(1L));
}

@Test
public void containsValue_validBehavior_ok() {
map.put(1L, "first value");
assertTrue(map.containsValue("first value"));
}

@Test
public void containsValue_invalidBehavior_notOk() {
assertFalse(map.containsValue("first value"));
}

@Test
public void keys_validBehavior_ok() {
Long[] expected = new Long[] {1L, 2L, 3L};
map.put(expected[0], "first value");
map.put(expected[1], "second value");
map.put(expected[2], "third value");
long[] actual = map.keys();
for (int i = 0; i < 3; i++) {
assertEquals(expected[i], (Long)actual[i]);
}
}

@Test
public void values_validBehavior_ok() {
String[] expected = new String[] {"first value", "second value", "third value"};
map.put(1L, "first value");
map.put(2L, "second value");
map.put(3L, "third value");
String[] actual = map.values();
for (int i = 0; i < 3; i++) {
assertEquals(expected[i], actual[i]);
}
}

@Test
public void size_validBehavior_ok() {
map.put(1L, "first value");
map.put(2L, "second value");
map.put(3L, "third value");
assertEquals(3L, map.size());
}

@Test
public void clear_validBehavior_ok() {
map.put(1L, "first value");
map.clear();
assertNull(map.get(1L));
}
}