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
42 changes: 42 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
23 changes: 23 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>long-map</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
8 changes: 8 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
276 changes: 247 additions & 29 deletions src/main/java/de/comparus/opensource/longmap/LongMapImpl.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,261 @@
package de.comparus.opensource.longmap;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class LongMapImpl<V> implements LongMap<V> {
public V put(long key, V value) {
return null;
}

public V get(long key) {
return null;
}
private static final int DEFAULT_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;

private int capacity;
private float loadFactor;
private int size;
private Entry<V>[] buckets;
long[] keysCache = null;
V[] valuesCache = null;

Class<V> type = (Class<V>) Object.class;

public LongMapImpl() {
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, null);
}

public LongMapImpl(Class<V> type) {
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, type);
}

public LongMapImpl(int capacity, float loadFactor, Class<V> type) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"Capacity can not be less zero." + System.lineSeparator() + "Invalid capacity: " + capacity);
}
if (loadFactor <= 0 || loadFactor > 1) {
throw new IllegalArgumentException("The value of the load factor can only be in the range of 0 to 1"
+ System.lineSeparator() + "Invalid load factor: " + loadFactor);
}

this.type = type;
this.capacity = capacity;
this.loadFactor = loadFactor;
this.size = 0;
this.buckets = new Entry[capacity];
}

public V put(long key, V value) {
keysCache = null;
valuesCache = null;
if (type == null || type == Object.class) {
type = (Class<V>) value.getClass();
} else if (value.getClass() != type) {
throw new IllegalArgumentException(
"Invalid value type. Available only " + type.getName() + "values for inserting");
}
int bucketIndex = getBucketIndex(key, capacity);
Entry<V> bucketEntry = buckets[bucketIndex];
if (bucketEntry != null) {
Entry<V> lastNotNullEntry = null;
while (bucketEntry != null) {
if (bucketEntry.getKey() == key) {
V prevValue = bucketEntry.getValue();
lastNotNullEntry.next = bucketEntry;
bucketEntry.setValue(value);
return prevValue;
}
lastNotNullEntry = bucketEntry;
bucketEntry = bucketEntry.next;

}
lastNotNullEntry.next = new Entry<V>(key, value);

} else {
buckets[bucketIndex] = new Entry<V>(key, value);
}
size++;

if (size > capacity * loadFactor) {
resize();
}
return null;
}

public V get(long key) {
int bucketIndex = getBucketIndex(key, capacity);
Entry<V> bucketEntry = buckets[bucketIndex];
if (bucketEntry == null) {
return null;
} else if (bucketEntry.getKey() == key) {
return bucketEntry.getValue();
} else {
Entry<V> prevEntry = null;
while (bucketEntry != null) {
prevEntry = bucketEntry;
bucketEntry = prevEntry.next;
if (bucketEntry.getKey() == key) {
return bucketEntry.getValue();
}
}
}

return null;
}

public V remove(long key) {
keysCache = null;
valuesCache = null;
int bucketIndex = getBucketIndex(key, capacity);
Entry<V> bucketEntry = buckets[bucketIndex];
if (bucketEntry == null) {
return null;
} else if (bucketEntry.getKey() == key) {
V value = bucketEntry.getValue();
buckets[bucketIndex] = null;
size--;
return value;
} else {
Entry<V> prevEntry = null;
while (bucketEntry != null) {
prevEntry = bucketEntry;
bucketEntry = prevEntry.next;
if (bucketEntry.getKey() == key) {
Entry<V> nextEntry = bucketEntry.next;
prevEntry.next = nextEntry;
size--;
return bucketEntry.getValue();
}
}
}
return null;
}

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

public boolean containsKey(long key) {
int bucketIndex = getBucketIndex(key, capacity);
Entry<V> bucketEntry = buckets[bucketIndex];
if (bucketEntry != null) {
while (bucketEntry != null) {
if (bucketEntry.getKey() == key) {
return true;
}
bucketEntry = bucketEntry.next;
}
}
return false;
}

public boolean containsValue(V value) {
V[] values = values();
return Arrays.asList(values).contains(value);
}

public long[] keys() {
if (keysCache != null) {
return keysCache;
}
Set<Long> keySet = new HashSet<Long>();
for (Entry<V> entry : buckets) {
if (entry != null) {
while (entry != null) {
keySet.add(entry.getKey());
entry = entry.next;

}
}
}

long[] keys = new long[keySet.size()];
int i = 0;
for (long key : keySet) {
keys[i++] = key;
}
keysCache = keys;
return keys;
}

@SuppressWarnings("unchecked")
public V[] values() {
if (valuesCache != null) {
return valuesCache;
}
int i = 0;
V[] values = (V[]) Array.newInstance(type, size);
for (Entry<V> entry : buckets) {
if (entry != null) {
while (entry != null) {
values[i] = entry.getValue();
i++;
entry = entry.next;

}
}
}
valuesCache = values;
return values;
}

public long size() {
return size;
}

public void clear() {
size = 0;
buckets = new Entry[capacity];
}

private static class Entry<V> {
private long key;
private V value;

public V remove(long key) {
return null;
}
private Entry<V> next;

public boolean isEmpty() {
return false;
}
public Entry(long key, V value) {
this.key = key;
this.value = value;
}

public boolean containsKey(long key) {
return false;
}
public long getKey() {
return key;
}

public boolean containsValue(V value) {
return false;
}
public V getValue() {
return value;
}

public long[] keys() {
return null;
}
public void setValue(V value) {
this.value = value;
}
}

public V[] values() {
return null;
}
private void resize() {
int newCapacity = capacity + capacity / 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
}
Entry<V>[] newBuckets = new Entry[newCapacity];

public long size() {
return 0;
}
for (Entry<V> bucket : buckets) {
while (bucket != null) {
int newBucketIndex = getBucketIndex(bucket.getKey(), newCapacity);
Entry<V> newBucket = newBuckets[newBucketIndex];
if (newBucket == null) {
newBuckets[newBucketIndex] = bucket;
} else {
newBucket.next = bucket;
}
bucket = bucket.next;
}
}

public void clear() {
capacity = newCapacity;
buckets = newBuckets;
}

}
private int getBucketIndex(long key, int capacity) {
return ((int) Math.abs(key) % capacity);
}
}
Loading