Created
May 15, 2025 07:15
-
-
Save untainsYD/c216352a0b8204ce865fec1aa12989c1 to your computer and use it in GitHub Desktop.
Створення власного контейнера на базі масиву
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package lab4.container; | |
import java.util.AbstractList; | |
import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.ListIterator; | |
import java.util.NoSuchElementException; | |
import java.util.Objects; | |
/** | |
* Узагальнений клас, що представляє одновимірний масив з діапазоном індексів від from до to (включно) | |
* @param <E> тип елементів масиву | |
*/ | |
public class IndexedArray<E> extends AbstractList<E> { | |
private final Object[] elements; | |
private final int from; | |
private final int to; | |
/** | |
* Конструктор за замовчуванням, створює порожній масив з індексами від 0 до -1 | |
*/ | |
public IndexedArray() { | |
this(0, -1); | |
} | |
/** | |
* Створює порожній масив із заданим діапазоном індексів | |
* @param from початковий індекс (включно) | |
* @param to кінцевий індекс (включно) | |
*/ | |
public IndexedArray(int from, int to) { | |
if (to < from) { | |
throw new IllegalArgumentException("Кінцевий індекс не може бути меншим за початковий: from=" + from + ", to=" + to); | |
} | |
this.from = from; | |
this.to = to; | |
int size = to - from + 1; | |
this.elements = new Object[size]; | |
} | |
/** | |
* Створює масив із заданим діапазоном індексів та колекцією елементів | |
* @param from початковий індекс (включно) | |
* @param to кінцевий індекс (включно) | |
* @param collection колекція елементів | |
*/ | |
public IndexedArray(int from, int to, Collection<? extends E> collection) { | |
if (to < from) { | |
throw new IllegalArgumentException("Кінцевий індекс не може бути меншим за початковий: from=" + from + ", to=" + to); | |
} | |
int size = to - from + 1; | |
if (collection.size() > size) { | |
throw new IllegalArgumentException("Розмір колекції перевищує розмір масиву"); | |
} | |
this.from = from; | |
this.to = to; | |
this.elements = new Object[size]; | |
int i = 0; | |
for (E element : collection) { | |
elements[i++] = element; | |
} | |
} | |
/** | |
* Створює масив із заданим діапазоном індексів та масивом елементів | |
* @param from початковий індекс (включно) | |
* @param to кінцевий індекс (включно) | |
* @param elements масив елементів | |
*/ | |
@SafeVarargs | |
public IndexedArray(int from, int to, E... elements) { | |
if (to < from) { | |
throw new IllegalArgumentException("Кінцевий індекс не може бути меншим за початковий: from=" + from + ", to=" + to); | |
} | |
int size = to - from + 1; | |
if (elements.length > size) { | |
throw new IllegalArgumentException("Розмір масиву елементів перевищує розмір створюваного масиву"); | |
} | |
this.from = from; | |
this.to = to; | |
this.elements = new Object[size]; | |
System.arraycopy(elements, 0, this.elements, 0, elements.length); | |
} | |
/** | |
* Перевіряє чи належить індекс допустимому діапазону | |
* @param index індекс для перевірки | |
* @return true, якщо індекс допустимий | |
*/ | |
private boolean isValidIndex(int index) { | |
return index >= from && index <= to; | |
} | |
/** | |
* Перетворює зовнішній індекс на внутрішній (зсунутий відносно from) | |
* @param externalIndex зовнішній індекс | |
* @return внутрішній індекс | |
*/ | |
private int toInternalIndex(int externalIndex) { | |
if (!isValidIndex(externalIndex)) { | |
throw new IndexOutOfBoundsException("Індекс поза межами допустимого діапазону: " + externalIndex + | |
", допустимий діапазон: [" + from + ".." + to + "]"); | |
} | |
return externalIndex - from; | |
} | |
/** | |
* Перетворює внутрішній індекс на зовнішній | |
* @param internalIndex внутрішній індекс | |
* @return зовнішній індекс | |
*/ | |
private int toExternalIndex(int internalIndex) { | |
return internalIndex + from; | |
} | |
/** | |
* Повертає розмір масиву | |
* @return кількість елементів | |
*/ | |
@Override | |
public int size() { | |
return to - from + 1; | |
} | |
/** | |
* Перевіряє чи порожній масив | |
* @return true, якщо масив порожній | |
*/ | |
@Override | |
public boolean isEmpty() { | |
return size() == 0; | |
} | |
/** | |
* Перевіряє чи містить масив заданий елемент | |
* @param o елемент для перевірки | |
* @return true, якщо елемент знайдено | |
*/ | |
@Override | |
public boolean contains(Object o) { | |
return indexOf(o) >= from; | |
} | |
/** | |
* Повертає ітератор для обходу елементів масиву | |
* @return ітератор | |
*/ | |
@Override | |
public Iterator<E> iterator() { | |
return new Iterator<E>() { | |
private int cursor = 0; | |
@Override | |
public boolean hasNext() { | |
return cursor < size(); | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public E next() { | |
if (!hasNext()) { | |
throw new NoSuchElementException(); | |
} | |
return (E) elements[cursor++]; | |
} | |
}; | |
} | |
/** | |
* Повертає масив, що містить всі елементи | |
* @return масив об'єктів | |
*/ | |
@Override | |
public Object[] toArray() { | |
return Arrays.copyOf(elements, size()); | |
} | |
/** | |
* Повертає масив заданого типу, що містить всі елементи | |
* @param a масив, в який будуть скопійовані елементи | |
* @return масив елементів | |
*/ | |
@Override | |
@SuppressWarnings("unchecked") | |
public <T> T[] toArray(T[] a) { | |
int size = size(); | |
if (a.length < size) { | |
return (T[]) Arrays.copyOf(elements, size, a.getClass()); | |
} | |
System.arraycopy(elements, 0, a, 0, size); | |
if (a.length > size) { | |
a[size] = null; | |
} | |
return a; | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean add(E e) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean remove(Object o) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Перевіряє чи містить масив усі елементи із заданої колекції | |
* @param c колекція для перевірки | |
* @return true, якщо всі елементи знайдено | |
*/ | |
@Override | |
public boolean containsAll(Collection<?> c) { | |
for (Object e : c) { | |
if (!contains(e)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean addAll(Collection<? extends E> c) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean addAll(int index, Collection<? extends E> c) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean removeAll(Collection<?> c) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public boolean retainAll(Collection<?> c) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Встановлює всі елементи масиву в null | |
*/ | |
@Override | |
public void clear() { | |
Arrays.fill(elements, null); | |
} | |
/** | |
* Повертає елемент за заданим індексом | |
* @param index індекс елемента | |
* @return елемент | |
*/ | |
@Override | |
@SuppressWarnings("unchecked") | |
public E get(int index) { | |
return (E) elements[toInternalIndex(index)]; | |
} | |
/** | |
* Встановлює нове значення елемента за заданим індексом | |
* @param index індекс елемента | |
* @param element нове значення | |
* @return попереднє значення | |
*/ | |
@Override | |
@SuppressWarnings("unchecked") | |
public E set(int index, E element) { | |
int internalIndex = toInternalIndex(index); | |
E oldValue = (E) elements[internalIndex]; | |
elements[internalIndex] = element; | |
return oldValue; | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public void add(int index, E element) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Цей метод не підтримується, оскільки масив має фіксований розмір | |
*/ | |
@Override | |
public E remove(int index) { | |
throw new UnsupportedOperationException("Масив має фіксований розмір"); | |
} | |
/** | |
* Знаходить індекс першого входження заданого елемента | |
* @param o елемент для пошуку | |
* @return індекс елемента або -1, якщо елемент не знайдено | |
*/ | |
@Override | |
public int indexOf(Object o) { | |
for (int i = 0; i < elements.length; i++) { | |
if (Objects.equals(o, elements[i])) { | |
return toExternalIndex(i); | |
} | |
} | |
return -1; | |
} | |
/** | |
* Знаходить індекс останнього входження заданого елемента | |
* @param o елемент для пошуку | |
* @return індекс елемента або -1, якщо елемент не знайдено | |
*/ | |
@Override | |
public int lastIndexOf(Object o) { | |
for (int i = elements.length - 1; i >= 0; i--) { | |
if (Objects.equals(o, elements[i])) { | |
return toExternalIndex(i); | |
} | |
} | |
return -1; | |
} | |
/** | |
* Повертає рядкове представлення масиву | |
* @return рядок з елементами масиву | |
*/ | |
@Override | |
public String toString() { | |
StringBuilder sb = new StringBuilder(); | |
sb.append("IndexedArray{"); | |
sb.append("range=[").append(from).append("..").append(to).append("], "); | |
sb.append("elements=["); | |
for (int i = from; i <= to; i++) { | |
if (i > from) { | |
sb.append(", "); | |
} | |
sb.append(i).append(":").append(get(i)); | |
} | |
sb.append("]}"); | |
return sb.toString(); | |
} | |
/** | |
* Повертає початковий індекс масиву | |
* @return початковий індекс | |
*/ | |
public int getFrom() { | |
return from; | |
} | |
/** | |
* Повертає кінцевий індекс масиву | |
* @return кінцевий індекс | |
*/ | |
public int getTo() { | |
return to; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment