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
15 changes: 14 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,24 @@
</build>

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
65 changes: 65 additions & 0 deletions src/main/java/de/comparus/opensource/longmap/LongMap.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,82 @@
package de.comparus.opensource.longmap;

/**
* A map with keys of type long.
*
* @param <V> the type of values stored in the map
*/
public interface LongMap<V> {
/**
* Associates the specified value with the specified key in this map.
*
* @param key the key with which the specified value is to be associated
* @param value the value to be associated with the specified key
* @return the previous value associated with the key, or null if there was no mapping for the key
*/
V put(long key, V value);

/**
* Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or null if this map contains no mapping for the key
*/
V get(long key);

/**
* Removes the mapping for the specified key from this map if present.
*
* @param key the key whose mapping is to be removed from the map
* @return the previous value associated with the key, or null if there was no mapping for the key
*/
V remove(long key);

/**
* Returns true if this map contains no key-value mappings.
*
* @return true if this map contains no key-value mappings
*/
boolean isEmpty();

/**
* Returns true if this map contains a mapping for the specified key.
*
* @param key the key whose presence in this map is to be tested
* @return true if this map contains a mapping for the specified key
*/
boolean containsKey(long key);

/**
* Returns true if this map contains at least one mapping with the specified value.
*
* @param value the value whose presence in this map is to be tested
* @return true if this map contains at least one mapping with the specified value
*/
boolean containsValue(V value);

/**
* Returns an array containing all the keys in this map.
*
* @return an array containing all the keys in this map
*/
long[] keys();

/**
* Returns an array containing all the values in this map.
*
* @return an array containing all the values in this map
*/
V[] values();

/**
* Returns the number of key-value mappings in this map.
*
* @return the number of key-value mappings in this map
*/
long size();

/**
* Removes all of the mappings from this map. The map will be empty after this call returns.
*/
void clear();
}
152 changes: 146 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,183 @@
package de.comparus.opensource.longmap;

import lombok.AllArgsConstructor;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class LongMapImpl<V> implements LongMap<V> {

private static final int CAPACITY_LEVEL = 2;
private static final int DEFAULT_CAPACITY = 16;
private static final double LOAD_FACTOR = 0.75;

private Entry<V>[] table;
private int size;

public LongMapImpl() {
this(DEFAULT_CAPACITY);
}

public LongMapImpl(int initialCapacity) {
if (initialCapacity <= 0) {
throw new IllegalArgumentException("Initial capacity must be positive");
}
table = new Entry[initialCapacity];
size = 0;
}

@Override
public V put(long key, V value) {
return null;
if (size >= table.length * LOAD_FACTOR) {
resize();
}
int index = hash(key) % table.length;

Entry<V> entry = table[index];
while (entry != null) {
if (entry.key == key) {
entry.value = value;
return value;
}
entry = entry.next;
}

table[index] = new Entry<>(key, value, table[index]);
size++;
return value;
}

@Override
public V get(long key) {
int index = hash(key) % table.length;
Entry<V> entry = table[index];
while (entry != null) {
if (entry.key == key) {
return entry.value;
}
entry = entry.next;
}
return null;
}

@Override
public V remove(long key) {
return null;
int index = hash(key) % table.length;
Entry<V> prev = null;
Entry<V> current = table[index];

while (current != null) {
if (current.key == key) {
if (prev == null) {
table[index] = current.next;
} else {
prev.next = current.next;
}
size--;
return current.value;
}
prev = current;
current = current.next;
}
return prev != null ? prev.value : null;
}

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

@Override
public boolean containsKey(long key) {
int index = hash(key) % table.length;
Entry<V> entry = table[index];
while (entry != null) {
if (entry.key == key) {
return true;
}
entry = entry.next;
}
return false;
}

@Override
public boolean containsValue(V value) {
for (Entry<V> entry : table) {
while (entry != null) {
if (Objects.equals(entry.value, value)) {
return true;
}
entry = entry.next;
}
}
return false;
}

@Override
public long[] keys() {
return null;
long[] keys = new long[(int) size()];
int index = 0;
for (Entry<V> entry : table) {
while (entry != null) {
keys[index++] = entry.key;
entry = entry.next;
}
}
return keys;
}

@Override
public V[] values() {
return null;
List<V> valueList = new ArrayList<>();
for (Entry<V> entry : table) {
while (entry != null) {
valueList.add(entry.value);
entry = entry.next;
}
}
return valueList.toArray((V[]) Array.newInstance(valueList.get(0).getClass(), valueList.size()));
}

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

@Override
public void clear() {
if ((table) != null && size > 0) {
size = 0;
Arrays.fill(table, null);
}
}

private int hash(long key) {
return Long.hashCode(key);
}

private void resize() {
int newCapacity = table.length * CAPACITY_LEVEL;
Entry<V>[] newTable = new Entry[newCapacity];

for (Entry<V> entry : table) {
while (entry != null) {
int index = hash(entry.key) % newCapacity;
Entry<V> next = entry.next;
entry.next = newTable[index];
newTable[index] = entry;
entry = next;
}
}
table = newTable;
}

@AllArgsConstructor
private static class Entry<V> {
long key;
V value;
Entry<V> next;
}
}
Loading