Skip to content

Commit 3f5ca19

Browse files
committed
UNFINISHED: implement Collection by CustomHashSet
1 parent 8eac8a0 commit 3f5ca19

File tree

6 files changed

+208
-20
lines changed

6 files changed

+208
-20
lines changed

src/main/java/by/andd3dfx/collections/custom/CustomHashMap.java

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public boolean isEmpty() {
2626
return size == 0;
2727
}
2828

29-
public V get(K key) {
29+
public V get(Object key) {
3030
if (key == null) {
3131
return valueForNullKey;
3232
}
@@ -53,7 +53,7 @@ public V put(K key, V value) {
5353

5454
int bucketNumber = determineBucketNumber(key);
5555
if (buckets[bucketNumber].isEmpty()) {
56-
buckets[bucketNumber].add(new CustomEntry(key, value));
56+
buckets[bucketNumber].add(new CustomEntry<>(key, value));
5757
size++;
5858
return null;
5959
}
@@ -66,12 +66,12 @@ public V put(K key, V value) {
6666
}
6767
}
6868

69-
buckets[bucketNumber].add(new CustomEntry(key, value));
69+
buckets[bucketNumber].add(new CustomEntry<>(key, value));
7070
size++;
7171
return null;
7272
}
7373

74-
public boolean containsKey(K key) {
74+
public boolean containsKey(Object key) {
7575
return get(key) != null;
7676
}
7777

@@ -86,7 +86,7 @@ public boolean containsValue(V value) {
8686
return false;
8787
}
8888

89-
public V remove(K key) {
89+
public V remove(Object key) {
9090
if (key == null) {
9191
var result = valueForNullKey;
9292
valueForNullKey = null;
@@ -95,13 +95,19 @@ public V remove(K key) {
9595
}
9696

9797
int bucketNumber = determineBucketNumber(key);
98-
for (var curr : buckets[bucketNumber]) {
98+
var bucket = buckets[bucketNumber];
99+
var iterator = bucket.iterator();
100+
int index = 0;
101+
102+
while (iterator.hasNext()) {
103+
var curr = iterator.next();
99104
if (checkEquality(key, curr.getKey())) {
100105
final V result = curr.getValue();
101-
buckets[bucketNumber].remove(curr);
106+
bucket.remove(index);
102107
size--;
103108
return result;
104109
}
110+
index++;
105111
}
106112
return null;
107113
}
@@ -122,14 +128,16 @@ Iterator<K> keyIterator() {
122128
return new KeyIterator<>(buckets);
123129
}
124130

125-
private int determineBucketNumber(K key) {
131+
private int determineBucketNumber(Object key) {
126132
return Math.abs(key.hashCode() % BUCKETS_COUNT);
127133
}
128134

129135
private class KeyIterator<E> implements Iterator<E> {
130136
private final CustomLinkedList<CustomEntry<E, V>>[] buckets;
131137
private int currentBucketIndex;
132138
private Iterator<CustomEntry<E, V>> currentIterator;
139+
private CustomEntry<E, V> lastReturned;
140+
private boolean canRemove = false;
133141

134142
public KeyIterator(CustomLinkedList<CustomEntry<E, V>>[] buckets) {
135143
this.buckets = buckets;
@@ -153,7 +161,9 @@ public boolean hasNext() {
153161
@Override
154162
public E next() {
155163
if (currentIterator.hasNext()) {
156-
return currentIterator.next().getKey();
164+
lastReturned = currentIterator.next();
165+
canRemove = true;
166+
return lastReturned.getKey();
157167
}
158168
if (currentBucketIndex < buckets.length - 1) {
159169
currentBucketIndex++;
@@ -162,6 +172,29 @@ public E next() {
162172
}
163173
throw new NoSuchElementException();
164174
}
175+
176+
@Override
177+
public void remove() {
178+
if (!canRemove) {
179+
throw new IllegalStateException("remove() can only be called after next()");
180+
}
181+
if (lastReturned != null) {
182+
// Находим индекс элемента в текущем bucket и удаляем его
183+
var bucket = buckets[currentBucketIndex];
184+
var iterator = bucket.iterator();
185+
int index = 0;
186+
while (iterator.hasNext()) {
187+
var curr = iterator.next();
188+
if (curr == lastReturned) {
189+
bucket.remove(index);
190+
size--;
191+
canRemove = false;
192+
return;
193+
}
194+
index++;
195+
}
196+
}
197+
}
165198
}
166199

167200
@Override
@@ -182,6 +215,7 @@ private boolean checkEquality(Object o1, Object o2) {
182215
return o1.equals(o2);
183216
}
184217

218+
@SuppressWarnings("unchecked")
185219
private void initialize() {
186220
buckets = new CustomLinkedList[BUCKETS_COUNT];
187221
for (var i = 0; i < BUCKETS_COUNT; i++) {

src/main/java/by/andd3dfx/collections/custom/CustomHashSet.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11
package by.andd3dfx.collections.custom;
22

3+
import java.util.Arrays;
34
import java.util.Collection;
45
import java.util.Iterator;
6+
import java.util.stream.Stream;
57

68
/**
79
* @see <a href="https://youtu.be/aTbKxApYNYk">Video solution</a>
810
*/
9-
public class CustomHashSet<T> implements Iterable<T> {
11+
public class CustomHashSet<T> implements Collection<T> {
1012

1113
private CustomHashMap<T, Object> map = new CustomHashMap<>();
1214
private static final Object DUMMY_VALUE = new Object();
1315

16+
@Override
1417
public int size() {
1518
return map.size();
1619
}
1720

21+
@Override
1822
public boolean isEmpty() {
1923
return map.isEmpty();
2024
}
2125

26+
@Override
2227
public boolean add(T item) {
2328
return map.put(item, DUMMY_VALUE) == null;
2429
}
2530

26-
public boolean addAll(Collection<T> items) {
31+
@Override
32+
public boolean addAll(Collection<? extends T> items) {
2733
boolean result = false;
2834
for (var item : items) {
2935
if (add(item)) {
@@ -33,11 +39,13 @@ public boolean addAll(Collection<T> items) {
3339
return result;
3440
}
3541

36-
public boolean remove(T item) {
42+
@Override
43+
public boolean remove(Object item) {
3744
return map.remove(item) == DUMMY_VALUE;
3845
}
3946

40-
public boolean removeAll(Collection<T> items) {
47+
@Override
48+
public boolean removeAll(Collection<?> items) {
4149
boolean result = false;
4250
for (var item : items) {
4351
if (remove(item)) {
@@ -47,11 +55,28 @@ public boolean removeAll(Collection<T> items) {
4755
return result;
4856
}
4957

50-
public boolean contains(T item) {
58+
@Override
59+
public boolean retainAll(Collection<?> c) {
60+
var modified = false;
61+
final Iterator<T> iterator = iterator();
62+
63+
while (iterator.hasNext()) {
64+
final T item = iterator.next();
65+
if (!c.contains(item)) {
66+
iterator.remove();
67+
modified = true;
68+
}
69+
}
70+
return modified;
71+
}
72+
73+
@Override
74+
public boolean contains(Object item) {
5175
return map.containsKey(item);
5276
}
5377

54-
public boolean containsAll(Collection<T> items) {
78+
@Override
79+
public boolean containsAll(Collection<?> items) {
5580
for (var item : items) {
5681
if (!map.containsKey(item)) {
5782
return false;
@@ -60,6 +85,7 @@ public boolean containsAll(Collection<T> items) {
6085
return true;
6186
}
6287

88+
@Override
6389
public void clear() {
6490
map.clear();
6591
}
@@ -69,6 +95,26 @@ public Iterator<T> iterator() {
6995
return map.keyIterator();
7096
}
7197

98+
@Override
99+
public Object[] toArray() {
100+
var list = new CustomArrayList<>();
101+
var iterator = map.keyIterator();
102+
while (iterator.hasNext()) {
103+
list.add(iterator.next());
104+
}
105+
return list.toArray();
106+
}
107+
108+
@Override
109+
public <T1> T1[] toArray(T1[] a) {
110+
var src = toArray();
111+
var result = (T1[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size());
112+
113+
System.arraycopy(src, 0, result, 0, size());
114+
115+
return result;
116+
}
117+
72118
@Override
73119
public String toString() {
74120
StringBuilder sb = new StringBuilder();

src/main/java/by/andd3dfx/collections/custom/CustomLinkedHashSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public boolean add(T item) {
1919
}
2020

2121
@Override
22-
public boolean remove(T item) {
22+
public boolean remove(Object item) {
2323
final boolean result = super.remove(item);
2424
if (result) {
2525
linkedList.remove(item);

src/main/java/by/andd3dfx/collections/custom/CustomLinkedList.java

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public T remove(int index) {
120120
return curr.value;
121121
}
122122

123-
public boolean remove(T value) {
123+
public boolean remove(Object value) {
124124
var i = 0;
125125
var curr = head;
126126
while (curr != null) {
@@ -134,7 +134,21 @@ public boolean remove(T value) {
134134
return false;
135135
}
136136

137-
private boolean checkEquality(T value1, T value2) {
137+
private boolean removeNode(Node<T> nodeToDelete) {
138+
var i = 0;
139+
var curr = head;
140+
while (curr != null) {
141+
if (checkEquality(nodeToDelete, curr)) {
142+
remove(i);
143+
return true;
144+
}
145+
i++;
146+
curr = curr.next;
147+
}
148+
return false;
149+
}
150+
151+
private boolean checkEquality(Object value1, Object value2) {
138152
if (value1 == null) {
139153
return value2 == null;
140154
}
@@ -169,12 +183,20 @@ public void clear() {
169183

170184
@Override
171185
public Iterator<T> iterator() {
172-
return new CustomIterator<>(head);
186+
return new CustomIterator<>(this);
173187
}
174188

175-
@AllArgsConstructor
176189
public static class CustomIterator<E> implements Iterator<E> {
190+
private final CustomLinkedList<E> list;
177191
private Node<E> curr;
192+
private Node<E> prevReturned;
193+
private boolean canRemove = false;
194+
195+
public CustomIterator(CustomLinkedList<E> list) {
196+
this.list = list;
197+
this.curr = list.head;
198+
this.prevReturned = null;
199+
}
178200

179201
@Override
180202
public boolean hasNext() {
@@ -183,10 +205,26 @@ public boolean hasNext() {
183205

184206
@Override
185207
public E next() {
208+
if (curr == null) {
209+
throw new IllegalStateException("No more elements");
210+
}
186211
var result = curr.value;
212+
prevReturned = curr;
187213
curr = curr.next;
214+
canRemove = true;
188215
return result;
189216
}
217+
218+
@Override
219+
public void remove() {
220+
if (!canRemove) {
221+
throw new IllegalStateException("remove() can only be called after next()");
222+
}
223+
if (prevReturned != null) {
224+
list.removeNode(prevReturned);
225+
canRemove = false;
226+
}
227+
}
190228
}
191229

192230
@Override

0 commit comments

Comments
 (0)