-
Notifications
You must be signed in to change notification settings - Fork 2
Added LinkedList and HashMap custom classes #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| public class GarriksCoolerLinkedList<K, E> extends GarriksLinkedList<K, E> { | ||
|
|
||
| public E getByKey(Object key) { | ||
| for (GarriksNode<K, E> node : this) { | ||
| if (node.getKey().equals(key)) { | ||
| return node.getItem(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| public K getKey(int index) { | ||
| return getNode(index).getKey(); | ||
| } | ||
|
|
||
| public void addMap(K key, E element) { | ||
| for (GarriksNode<K, E> node : this) { | ||
| if (node.getKey().equals(key)) { | ||
| node.setKey(key); | ||
| return; | ||
| } | ||
| } | ||
| add(element, key); | ||
| } | ||
|
|
||
| public boolean add(E o, K key) { | ||
| GarriksNode<K, E> prevNode = tail.getPrev(); | ||
| GarriksNode<K, E> newNode = new GarriksNode<>(o, key, tail, prevNode); | ||
| prevNode.setNext(newNode); | ||
| tail.setPrev(newNode); | ||
| len++; | ||
| return true; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.List; | ||
|
|
||
| public class GarriksHashMap<K, V> implements HashMapInterface<K, V> { | ||
| private final int MINIMAL_LEN_CAUSING_REPLACEMENT = 13; | ||
| private final int DEFAULT_CAPACITY = 16; | ||
| private final double DEFAULT_LOAD_FACTOR = 0.75; | ||
| private GarriksCoolerLinkedList<K, V>[] array; | ||
| private int capacity; | ||
| private double loadFactor; | ||
| private int len; | ||
|
|
||
| public GarriksHashMap() { | ||
| createNewHashMap(); | ||
| } | ||
|
|
||
| @Override | ||
| public int size() { | ||
iaulitin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return len; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isEmpty() { | ||
| return len == 0; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean containsKey(Object key) { | ||
| int bucket = getBucketNum(key); | ||
| if (array[bucket] != null) { | ||
| for (GarriksNode<K, V> node : array[bucket]) { | ||
| if (node.getKey().equals(key)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public boolean containsValue(Object value) { | ||
| for (GarriksLinkedList<K, V> bucket : array) { | ||
| if (bucket != null) { | ||
| for (GarriksNode<K, V> node : bucket) { | ||
| if (node.getItem().equals(value)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public Collection<V> values() { | ||
| List<V> result = new ArrayList<>(); | ||
| for (GarriksLinkedList<K, V> bucket : array) { | ||
| if (bucket != null) { | ||
| for (GarriksNode<K, V> node : bucket) { | ||
| result.add(node.getItem()); | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| @Override | ||
| public V put(K key, V value) { | ||
| checkSize(); | ||
| int bucket = getBucketNum(key); | ||
| createBucket(bucket); | ||
| array[bucket].addMap(key, value); | ||
| len++; | ||
| return value; | ||
| } | ||
|
|
||
| @Override | ||
| public V get(Object key) { | ||
| int bucket = getBucketNum(key); | ||
| return array[bucket].getByKey(key); | ||
| } | ||
|
|
||
| @Override | ||
| public V remove(Object key) { | ||
| checkSize(); | ||
iaulitin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| int bucket = getBucketNum(key); | ||
| V result = array[bucket].getByKey(key); | ||
| array[bucket].remove(result); | ||
| if (array[bucket].size() == 0) { | ||
| array[bucket] = null; | ||
| } | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А для чего потом зануляешь опустевший массив? Если для экономии памяти - не уверен, что стоит этим заниматься - там памяти мизер, а ты теперь вынужден всегда беспокоиться - есть у тебя список в бакете или нет. Если не допускать ситуацию наличия пустого бакета, жить будет лучше, жить будет веселей.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я это делал намеренно. Мне показалось, что так удобнее и быстрее проверять, есть ли элементы в корзине. Если корзина пустая, то соответсвующей ячейке присваевается null.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я бы оставлял. Во-первых, фактор сложности кода. Меньше действий - проще код. |
||
| len--; | ||
| return result; | ||
| } | ||
|
|
||
| @Override | ||
| public void clear() { | ||
| createNewHashMap(); | ||
| } | ||
|
|
||
| private int getBucketNum(Object key) { | ||
| return Math.abs(key.hashCode() % capacity); | ||
| } | ||
|
|
||
| private void checkSize() { | ||
| if (len > loadFactor * capacity) { | ||
| capacity *= 2; | ||
| replacementArray(); | ||
iaulitin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| if (len > MINIMAL_LEN_CAUSING_REPLACEMENT && capacity > len * loadFactor / 2) { | ||
| capacity /= 2; | ||
| replacementArray(); | ||
| } | ||
| } | ||
|
|
||
| private void replacementArray() { | ||
| GarriksCoolerLinkedList<K, V>[] newArray = new GarriksCoolerLinkedList[capacity]; | ||
| for (GarriksCoolerLinkedList<K, V> bucket : array) { | ||
| if (bucket == null) { | ||
| continue; | ||
| } | ||
| for (GarriksNode<K, V> node : bucket) { | ||
| if (newArray[getBucketNum(node.getKey())] == null) { | ||
| newArray[getBucketNum(node.getKey())] = new GarriksCoolerLinkedList<>(); | ||
| } | ||
| int bucketIndex = getBucketNum(node.getKey()); | ||
| K currKey = node.getKey(); | ||
| V currItem = node.getItem(); | ||
| newArray[bucketIndex].addMap(currKey, currItem); | ||
| } | ||
| } | ||
| array = newArray; | ||
| } | ||
|
|
||
| private void createBucket(int index) { | ||
| if (array[index] == null) { | ||
| array[index] = new GarriksCoolerLinkedList<>(); | ||
| } | ||
| } | ||
|
|
||
| private void createNewHashMap() { | ||
| array = new GarriksCoolerLinkedList[16]; | ||
| capacity = DEFAULT_CAPACITY; | ||
| loadFactor = DEFAULT_LOAD_FACTOR; | ||
| len = 0; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| StringBuilder result = new StringBuilder(); | ||
| for (GarriksLinkedList<K, V> bucket : array) { | ||
| result.append(bucket).append("\n"); | ||
| } | ||
| return result.toString(); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| import java.util.Iterator; | ||
|
|
||
| public class GarriksLinkedList<T, E> implements LinkedListInterface<E>, Iterable<GarriksNode<T, E>> { | ||
|
|
||
|
|
||
| protected final GarriksNode<T, E> head; | ||
| protected final GarriksNode<T, E> tail; | ||
| protected int len; | ||
|
|
||
| public GarriksLinkedList() { | ||
| this.head = new GarriksNode<>(null, null, null); | ||
| this.tail = new GarriksNode<>(null, null, head); | ||
| this.head.setNext(this.tail); | ||
| this.len = 0; | ||
| } | ||
|
|
||
| public GarriksNode<T, E> getHead() { | ||
| return head; | ||
| } | ||
|
|
||
| @Override | ||
| public int size() { | ||
| return len; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isEmpty() { | ||
| return len == 0; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean contains(Object o) { | ||
|
|
||
| if (isEmpty()) { | ||
| return false; | ||
| } | ||
|
|
||
| GarriksNode<T, E> currNode = head.getNext(); | ||
|
|
||
| if (currNode.getItem().getClass() != o.getClass()) { | ||
| return false; | ||
| } | ||
|
|
||
| while (currNode.getItem() != null && !currNode.getItem().equals(o)) { | ||
| currNode = currNode.getNext(); | ||
| } | ||
| return currNode.getItem() != null && currNode.getItem().equals(o); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean add(E o) { | ||
| GarriksNode<T, E> prevNode = tail.getPrev(); | ||
| GarriksNode<T, E> newNode = new GarriksNode<>(o, tail, prevNode); | ||
| prevNode.setNext(newNode); | ||
| tail.setPrev(newNode); | ||
| len++; | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public void add(int index, E element) { | ||
| GarriksNode<T, E> currNode = index == 0 ? head : getNode(index - 1); | ||
| GarriksNode<T, E> nextNode = currNode.getNext(); | ||
| GarriksNode<T, E> newNode = new GarriksNode<>(element, nextNode, currNode); | ||
| currNode.setNext(newNode); | ||
| nextNode.setPrev(newNode); | ||
| len++; | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public E get(int index) { | ||
| return getNode(index).getItem(); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public int indexOf(Object o) { | ||
| GarriksNode<T, E> currNode = head; | ||
| for (int i = 0; i < len; i++) { | ||
| currNode = currNode.getNext(); | ||
| if (o.equals(currNode.getItem())) { | ||
| return i; | ||
| } | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| @Override | ||
| public E set(int index, E element) { | ||
| getNode(index).setItem(element); | ||
| return element; | ||
| } | ||
|
|
||
| @Override | ||
| public E remove(int index) { | ||
| GarriksNode<T, E> currItem = getNode(index); | ||
| GarriksNode<T, E> prevItem = currItem.getPrev(); | ||
| GarriksNode<T, E> nextItem = currItem.getNext(); | ||
| prevItem.setNext(nextItem); | ||
| nextItem.setPrev(prevItem); | ||
| len--; | ||
| return currItem.getItem(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean remove(Object o) { | ||
| GarriksNode<T, E> currItem = getNode(o); | ||
| if (currItem.equals(tail) || currItem.equals(head)) { | ||
| return false; | ||
| } | ||
| GarriksNode<T, E> prevItem = currItem.getPrev(); | ||
| GarriksNode<T, E> nextItem = currItem.getNext(); | ||
| prevItem.setNext(nextItem); | ||
| nextItem.setPrev(prevItem); | ||
| len--; | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public void clear() { | ||
| head.setNext(tail); | ||
| tail.setPrev(head); | ||
| len = 0; | ||
| } | ||
|
|
||
| public Iterator<GarriksNode<T, E>> iterator() { | ||
| return new GarriksLinkedListIterator<>(this); | ||
| } | ||
|
|
||
| protected GarriksNode<T, E> getNode(int index) { | ||
| if (index >= len || index < 0) { | ||
| throw new IndexOutOfBoundsException(String.format("Attempt to get the index %d, in range 0..%d", index, len)); | ||
| } | ||
| GarriksNode<T, E> currNode = head; | ||
| for (int i = 0; i < index + 1; i++) { | ||
| currNode = currNode.getNext(); | ||
| } | ||
| return currNode; | ||
| } | ||
|
|
||
| protected GarriksNode<T, E> getNode(Object o) { | ||
| GarriksNode<T, E> currNode = head; | ||
| for (int i = 0; i < len; i++) { | ||
| if (currNode.getItem().equals(o)) { | ||
| return currNode; | ||
| } | ||
| currNode = currNode.getNext(); | ||
| } | ||
| return currNode; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| @Override | ||
| public String toString() { | ||
| GarriksNode<T, E> currElem = head; | ||
| StringBuilder result = new StringBuilder("head <-> "); | ||
| for (int i = 0; i < len; i++) { | ||
| currElem = currElem.getNext(); | ||
| result.append(currElem.getItem()).append(" <-> "); | ||
| } | ||
| result.append("tail"); | ||
|
|
||
| return result.toString(); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import java.util.Iterator; | ||
| import java.util.NoSuchElementException; | ||
|
|
||
| public class GarriksLinkedListIterator<T, E> implements Iterator<GarriksNode<T, E>> { | ||
iaulitin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| private GarriksNode<T, E> currElem; | ||
|
|
||
| public GarriksLinkedListIterator(GarriksLinkedList<T, E> arr) { | ||
| this.currElem = arr.getHead(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean hasNext() { | ||
| return currElem.getNext().getItem() != null; | ||
| } | ||
|
|
||
| @Override | ||
| public GarriksNode<T, E> next() { | ||
| if (!this.hasNext()) { | ||
| throw new NoSuchElementException("Garriks iterator can't see more elements :)"); | ||
| } | ||
| currElem = currElem.getNext(); | ||
| return currElem; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Эти константы могут быть статическими.
Обычно именно static final константы пишут в UPPER_SNAKE_CASE