Skip to content

Commit 5689570

Browse files
committed
extend dictionary API
1 parent ffc7a69 commit 5689570

7 files changed

Lines changed: 225 additions & 1 deletion

File tree

rlib-collections/src/main/java/javasabr/rlib/collections/dictionary/MutableIntToRefDictionary.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ static <V> MutableIntToRefDictionary<V> ofTypes(Class<V> valueType) {
2525
@Nullable
2626
V put(int key, V value);
2727

28+
/**
29+
* @return the previous value associated with the specified key, or null if there was no mapping for the key.
30+
*/
31+
@Nullable
32+
V putIfAbsent(int key, V value);
33+
2834
void putAll(IntToRefDictionary<? extends V> dictionary);
2935

3036
MutableIntToRefDictionary<V> append(IntToRefDictionary<? extends V> dictionary);
@@ -40,6 +46,11 @@ static <V> MutableIntToRefDictionary<V> ofTypes(Class<V> valueType) {
4046
@Nullable
4147
V remove(int key);
4248

49+
/**
50+
* @return true if the expectedValue was removed
51+
*/
52+
boolean remove(int key, V expectedValue);
53+
4354
/**
4455
* @return the optional value of the previous value for the key.
4556
*/

rlib-collections/src/main/java/javasabr/rlib/collections/dictionary/MutableLongToRefDictionary.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ static <V> MutableLongToRefDictionary<V> ofTypes(Class<V> valueType) {
2525
@Nullable
2626
V put(long key, V value);
2727

28+
/**
29+
* @return the previous value associated with the specified key, or null if there was no mapping for the key.
30+
*/
31+
@Nullable
32+
V putIfAbsent(long key, V value);
33+
2834
void putAll(LongToRefDictionary<? extends V> dictionary);
2935

3036
MutableLongToRefDictionary<V> append(LongToRefDictionary<? extends V> dictionary);
@@ -40,6 +46,11 @@ static <V> MutableLongToRefDictionary<V> ofTypes(Class<V> valueType) {
4046
@Nullable
4147
V remove(long key);
4248

49+
/**
50+
* @return true if the expectedValue was removed
51+
*/
52+
boolean remove(long key, V expectedValue);
53+
4354
/**
4455
* @return the optional value of the previous value for the key.
4556
*/

rlib-collections/src/main/java/javasabr/rlib/collections/dictionary/impl/AbstractMutableHashBasedIntToRefDictionary.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package javasabr.rlib.collections.dictionary.impl;
22

3+
import java.util.Objects;
34
import java.util.Optional;
45
import java.util.function.Function;
56
import java.util.function.IntFunction;
@@ -84,6 +85,23 @@ public V put(int key, V value) {
8485
return null;
8586
}
8687

88+
@Nullable
89+
@Override
90+
public V putIfAbsent(int key, V value) {
91+
@Nullable E[] entries = entries();
92+
int hash = hash(key);
93+
int entryIndex = indexFor(hash, entries.length);
94+
95+
for (E entry = entries[entryIndex]; entry != null; entry = entry.next()) {
96+
if (entry.hash() == hash && key == entry.key()) {
97+
return null;
98+
}
99+
}
100+
101+
addEntry(hash, key, value, entryIndex);
102+
return null;
103+
}
104+
87105
@Override
88106
public Optional<V> putOptional(int key, V value) {
89107
return Optional.ofNullable(put(key, value));
@@ -120,6 +138,37 @@ public V remove(int key) {
120138
return removed.value();
121139
}
122140

141+
@Override
142+
public boolean remove(int key, V expectedValue) {
143+
@Nullable E[] entries = entries();
144+
int hash = hash(key);
145+
int entryIndex = indexFor(hash, entries.length);
146+
147+
E previosEntry = entries[entryIndex];
148+
E entry = previosEntry;
149+
150+
while (entry != null) {
151+
E nextEntry = entry.next();
152+
if (entry.hash() == hash && key == entry.key()) {
153+
if (Objects.equals(entry.value(), expectedValue)) {
154+
decrementSize();
155+
if (previosEntry == entry) {
156+
entries[entryIndex] = nextEntry;
157+
} else {
158+
previosEntry.next(nextEntry);
159+
}
160+
return true;
161+
} else {
162+
return false;
163+
}
164+
}
165+
previosEntry = entry;
166+
entry = nextEntry;
167+
}
168+
169+
return false;
170+
}
171+
123172
@Override
124173
public Optional<V> removeOptional(int key) {
125174
return Optional.ofNullable(remove(key));

rlib-collections/src/main/java/javasabr/rlib/collections/dictionary/impl/AbstractMutableHashBasedLongToRefDictionary.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package javasabr.rlib.collections.dictionary.impl;
22

3+
import java.util.Objects;
34
import java.util.Optional;
45
import java.util.function.Function;
56
import java.util.function.LongFunction;
@@ -83,7 +84,24 @@ public V put(long key, V value) {
8384
addEntry(hash, key, value, entryIndex);
8485
return null;
8586
}
87+
88+
@Nullable
89+
@Override
90+
public V putIfAbsent(long key, V value) {
91+
@Nullable E[] entries = entries();
92+
int hash = hash(Long.hashCode(key));
93+
int entryIndex = indexFor(hash, entries.length);
94+
95+
for (E entry = entries[entryIndex]; entry != null; entry = entry.next()) {
96+
if (entry.hash() == hash && key == entry.key()) {
97+
return null;
98+
}
99+
}
86100

101+
addEntry(hash, key, value, entryIndex);
102+
return null;
103+
}
104+
87105
@Override
88106
public Optional<V> putOptional(long key, V value) {
89107
return Optional.ofNullable(put(key, value));
@@ -120,6 +138,37 @@ public V remove(long key) {
120138
return removed.value();
121139
}
122140

141+
@Override
142+
public boolean remove(long key, V expectedValue) {
143+
@Nullable E[] entries = entries();
144+
int hash = hash(Long.hashCode(key));
145+
int entryIndex = indexFor(hash, entries.length);
146+
147+
E previosEntry = entries[entryIndex];
148+
E entry = previosEntry;
149+
150+
while (entry != null) {
151+
E nextEntry = entry.next();
152+
if (entry.hash() == hash && key == entry.key()) {
153+
if (Objects.equals(entry.value(), expectedValue)) {
154+
decrementSize();
155+
if (previosEntry == entry) {
156+
entries[entryIndex] = nextEntry;
157+
} else {
158+
previosEntry.next(nextEntry);
159+
}
160+
return true;
161+
} else {
162+
return false;
163+
}
164+
}
165+
previosEntry = entry;
166+
entry = nextEntry;
167+
}
168+
169+
return false;
170+
}
171+
123172
@Override
124173
public Optional<V> removeOptional(long key) {
125174
return Optional.ofNullable(remove(key));

rlib-collections/src/main/java/javasabr/rlib/collections/dictionary/impl/AbstractMutableHashBasedRefToRefDictionary.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ public V put(K key, V value) {
8484
return null;
8585
}
8686

87-
@Override
8887
@Nullable
88+
@Override
8989
public V putIfAbsent(K key, V value) {
9090
@Nullable E[] entries = entries();
9191
int hash = hash(key.hashCode());

rlib-collections/src/test/java/javasabr/rlib/collections/dictionary/MutableIntToRefDictionaryTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,33 @@ void shouldPutNewPairs(MutableIntToRefDictionary<String> dictionary) {
3030
assertThat(dictionary.size()).isEqualTo(4);
3131
}
3232

33+
@ParameterizedTest
34+
@MethodSource("generateDictionaries")
35+
void shouldPutIfAbsentNewPairs(MutableIntToRefDictionary<String> dictionary) {
36+
// given:
37+
dictionary.put(1, "val1");
38+
dictionary.put(4, "val4");
39+
dictionary.put(7, "val7");
40+
dictionary.put(55, "val55");
41+
// when:
42+
String result1 = dictionary.putIfAbsent(1, "val1_1");
43+
String result2 = dictionary.putIfAbsent(4, "val4_1");
44+
String result3 = dictionary.putIfAbsent(44, "val44");
45+
// then:
46+
assertThat(result1).isNull();
47+
assertThat(result2).isNull();
48+
assertThat(result3).isNull();
49+
assertThat(dictionary.get(1)).isEqualTo("val1");
50+
assertThat(dictionary.get(4)).isEqualTo("val4");
51+
assertThat(dictionary.get(55)).isEqualTo("val55");
52+
assertThat(dictionary.get(44)).isEqualTo("val44");
53+
assertThat(dictionary.containsKey(1)).isTrue();
54+
assertThat(dictionary.containsKey(4)).isTrue();
55+
assertThat(dictionary.containsKey(55)).isTrue();
56+
assertThat(dictionary.containsKey(44)).isTrue();
57+
assertThat(dictionary.size()).isEqualTo(5);
58+
}
59+
3360
@ParameterizedTest
3461
@MethodSource("generateDictionaries")
3562
void shouldPutOptionalNewPairs(MutableIntToRefDictionary<String> dictionary) {
@@ -72,6 +99,31 @@ void shouldRemoveByKeys(MutableIntToRefDictionary<String> dictionary) {
7299
assertThat(dictionary.size()).isEqualTo(2);
73100
}
74101

102+
@ParameterizedTest
103+
@MethodSource("generateDictionaries")
104+
void shouldRemoveByKeysWithExpectedValues(MutableIntToRefDictionary<String> dictionary) {
105+
// given:
106+
dictionary.put(1, "val1");
107+
dictionary.put(4, "val4");
108+
dictionary.put(7, "val7");
109+
dictionary.put(55, "val55");
110+
111+
// when:
112+
boolean removed1 = dictionary.remove(1, "val2");
113+
boolean removed2 = dictionary.remove(55, "val55");
114+
115+
// then:
116+
assertThat(removed1).isFalse();
117+
assertThat(removed2).isTrue();
118+
assertThat(dictionary.get(4)).isEqualTo("val4");
119+
assertThat(dictionary.get(7)).isEqualTo("val7");
120+
assertThat(dictionary.get(1)).isEqualTo("val1");
121+
assertThat(dictionary.get(55)).isNull();
122+
assertThat(dictionary.containsKey(1)).isTrue();
123+
assertThat(dictionary.containsKey(55)).isFalse();
124+
assertThat(dictionary.size()).isEqualTo(3);
125+
}
126+
75127
@ParameterizedTest
76128
@MethodSource("generateDictionaries")
77129
void shouldRemoveOptionalByKeys(MutableIntToRefDictionary<String> dictionary) {

rlib-collections/src/test/java/javasabr/rlib/collections/dictionary/MutableLongToRefDictionaryTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,33 @@ void shouldPutNewPairs(MutableLongToRefDictionary<String> dictionary) {
3030
assertThat(dictionary.size()).isEqualTo(4);
3131
}
3232

33+
@ParameterizedTest
34+
@MethodSource("generateDictionaries")
35+
void shouldPutIfAbsentNewPairs(MutableLongToRefDictionary<String> dictionary) {
36+
// given:
37+
dictionary.put(1, "val1");
38+
dictionary.put(4, "val4");
39+
dictionary.put(7, "val7");
40+
dictionary.put(55, "val55");
41+
// when:
42+
String result1 = dictionary.putIfAbsent(1, "val1_1");
43+
String result2 = dictionary.putIfAbsent(4, "val4_1");
44+
String result3 = dictionary.putIfAbsent(44, "val44");
45+
// then:
46+
assertThat(result1).isNull();
47+
assertThat(result2).isNull();
48+
assertThat(result3).isNull();
49+
assertThat(dictionary.get(1)).isEqualTo("val1");
50+
assertThat(dictionary.get(4)).isEqualTo("val4");
51+
assertThat(dictionary.get(55)).isEqualTo("val55");
52+
assertThat(dictionary.get(44)).isEqualTo("val44");
53+
assertThat(dictionary.containsKey(1)).isTrue();
54+
assertThat(dictionary.containsKey(4)).isTrue();
55+
assertThat(dictionary.containsKey(55)).isTrue();
56+
assertThat(dictionary.containsKey(44)).isTrue();
57+
assertThat(dictionary.size()).isEqualTo(5);
58+
}
59+
3360
@ParameterizedTest
3461
@MethodSource("generateDictionaries")
3562
void shouldPutOptionalNewPairs(MutableLongToRefDictionary<String> dictionary) {
@@ -72,6 +99,31 @@ void shouldRemoveByKeys(MutableLongToRefDictionary<String> dictionary) {
7299
assertThat(dictionary.size()).isEqualTo(2);
73100
}
74101

102+
@ParameterizedTest
103+
@MethodSource("generateDictionaries")
104+
void shouldRemoveByKeysWithExpectedValues(MutableLongToRefDictionary<String> dictionary) {
105+
// given:
106+
dictionary.put(1, "val1");
107+
dictionary.put(4, "val4");
108+
dictionary.put(7, "val7");
109+
dictionary.put(55, "val55");
110+
111+
// when:
112+
boolean removed1 = dictionary.remove(1, "val2");
113+
boolean removed2 = dictionary.remove(55, "val55");
114+
115+
// then:
116+
assertThat(removed1).isFalse();
117+
assertThat(removed2).isTrue();
118+
assertThat(dictionary.get(4)).isEqualTo("val4");
119+
assertThat(dictionary.get(7)).isEqualTo("val7");
120+
assertThat(dictionary.get(1)).isEqualTo("val1");
121+
assertThat(dictionary.get(55)).isNull();
122+
assertThat(dictionary.containsKey(1)).isTrue();
123+
assertThat(dictionary.containsKey(55)).isFalse();
124+
assertThat(dictionary.size()).isEqualTo(3);
125+
}
126+
75127
@ParameterizedTest
76128
@MethodSource("generateDictionaries")
77129
void shouldRemoveOptionalByKeys(MutableLongToRefDictionary<String> dictionary) {

0 commit comments

Comments
 (0)