mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-05 08:17:33 +08:00
Enhance docs, add more tests in DynamicArray
(#5952)
This commit is contained in:
@ -10,21 +10,24 @@ import java.util.stream.Stream;
|
|||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a dynamic array.
|
* This class implements a dynamic array, which can grow or shrink in size
|
||||||
|
* as elements are added or removed. It provides an array-like interface
|
||||||
|
* with methods to add, remove, and access elements, along with iterators
|
||||||
|
* to traverse the elements.
|
||||||
*
|
*
|
||||||
* @param <E> the type that each index of the array will hold
|
* @param <E> the type of elements that this array can hold
|
||||||
*/
|
*/
|
||||||
public class DynamicArray<E> implements Iterable<E> {
|
public class DynamicArray<E> implements Iterable<E> {
|
||||||
|
|
||||||
private static final int DEFAULT_CAPACITY = 16;
|
private static final int DEFAULT_CAPACITY = 16;
|
||||||
private int size;
|
private int size;
|
||||||
private int modCount; // Tracks structural modifications for the iterator
|
private int modCount; // Tracks structural modifications for iterator integrity
|
||||||
private Object[] elements;
|
private Object[] elements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with initial capacity.
|
* Constructs a new DynamicArray with the specified initial capacity.
|
||||||
*
|
*
|
||||||
* @param capacity the starting length of the desired array
|
* @param capacity the initial capacity of the array
|
||||||
* @throws IllegalArgumentException if the specified capacity is negative
|
* @throws IllegalArgumentException if the specified capacity is negative
|
||||||
*/
|
*/
|
||||||
public DynamicArray(final int capacity) {
|
public DynamicArray(final int capacity) {
|
||||||
@ -37,14 +40,15 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-args constructor with default capacity.
|
* Constructs a new DynamicArray with a default initial capacity.
|
||||||
*/
|
*/
|
||||||
public DynamicArray() {
|
public DynamicArray() {
|
||||||
this(DEFAULT_CAPACITY);
|
this(DEFAULT_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an element to the array. If full, creates a new array with double the size.
|
* Adds an element to the end of the array. If the array is full, it
|
||||||
|
* creates a new array with double the size to accommodate the new element.
|
||||||
*
|
*
|
||||||
* @param element the element to be added to the array
|
* @param element the element to be added to the array
|
||||||
*/
|
*/
|
||||||
@ -55,11 +59,11 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Places an element at the desired index, expanding capacity if necessary.
|
* Places an element at the specified index, expanding capacity if necessary.
|
||||||
*
|
*
|
||||||
* @param index the index for the element to be placed
|
* @param index the index at which the element is to be placed
|
||||||
* @param element the element to be inserted
|
* @param element the element to be inserted at the specified index
|
||||||
* @throws IndexOutOfBoundsException if n is less than 0 or greater or equal to the number of elements in the array
|
* @throws IndexOutOfBoundsException if index is less than 0 or greater than or equal to the number of elements
|
||||||
*/
|
*/
|
||||||
public void put(final int index, E element) {
|
public void put(final int index, E element) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
@ -74,11 +78,11 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the element at a given index.
|
* Retrieves the element at the specified index.
|
||||||
*
|
*
|
||||||
* @param index the desired index of the element
|
* @param index the index of the element to retrieve
|
||||||
* @return the element at the specified index
|
* @return the element at the specified index
|
||||||
* @throws IndexOutOfBoundsException if n is less than 0 or greater or equal to the number of elements in the array
|
* @throws IndexOutOfBoundsException if index is less than 0 or greater than or equal to the current size
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public E get(final int index) {
|
public E get(final int index) {
|
||||||
@ -89,11 +93,11 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an element from the array.
|
* Removes and returns the element at the specified index.
|
||||||
*
|
*
|
||||||
* @param index the index of the element to be removed
|
* @param index the index of the element to be removed
|
||||||
* @return the element removed
|
* @return the element that was removed from the array
|
||||||
* @throws IndexOutOfBoundsException if n is less than 0 or greater or equal to the number of elements in the array
|
* @throws IndexOutOfBoundsException if index is less than 0 or greater than or equal to the current size
|
||||||
*/
|
*/
|
||||||
public E remove(final int index) {
|
public E remove(final int index) {
|
||||||
if (index < 0 || index >= size) {
|
if (index < 0 || index >= size) {
|
||||||
@ -106,16 +110,16 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the size of the array.
|
* Returns the current number of elements in the array.
|
||||||
*
|
*
|
||||||
* @return the size
|
* @return the number of elements in the array
|
||||||
*/
|
*/
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the array is empty.
|
* Checks whether the array is empty.
|
||||||
*
|
*
|
||||||
* @return true if the array contains no elements, false otherwise
|
* @return true if the array contains no elements, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -123,10 +127,20 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
return size == 0;
|
return size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a sequential stream with this collection as its source.
|
||||||
|
*
|
||||||
|
* @return a stream of the elements in the array
|
||||||
|
*/
|
||||||
public Stream<E> stream() {
|
public Stream<E> stream() {
|
||||||
return StreamSupport.stream(spliterator(), false);
|
return StreamSupport.stream(spliterator(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the array has enough capacity to hold the specified number of elements.
|
||||||
|
*
|
||||||
|
* @param minCapacity the minimum capacity required
|
||||||
|
*/
|
||||||
private void ensureCapacity(int minCapacity) {
|
private void ensureCapacity(int minCapacity) {
|
||||||
if (minCapacity > elements.length) {
|
if (minCapacity > elements.length) {
|
||||||
int newCapacity = Math.max(elements.length * 2, minCapacity);
|
int newCapacity = Math.max(elements.length * 2, minCapacity);
|
||||||
@ -134,6 +148,12 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the element at the specified index without resizing the array.
|
||||||
|
* This method shifts any subsequent elements to the left and clears the last element.
|
||||||
|
*
|
||||||
|
* @param index the index of the element to remove
|
||||||
|
*/
|
||||||
private void fastRemove(int index) {
|
private void fastRemove(int index) {
|
||||||
int numMoved = size - index - 1;
|
int numMoved = size - index - 1;
|
||||||
if (numMoved > 0) {
|
if (numMoved > 0) {
|
||||||
@ -142,31 +162,58 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
elements[--size] = null; // Clear to let GC do its work
|
elements[--size] = null; // Clear to let GC do its work
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the array, including only the elements that are currently stored.
|
||||||
|
*
|
||||||
|
* @return a string containing the elements in the array
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Arrays.toString(Arrays.copyOf(elements, size));
|
return Arrays.toString(Arrays.copyOf(elements, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over the elements in this array in proper sequence.
|
||||||
|
*
|
||||||
|
* @return an Iterator over the elements in the array
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterator<E> iterator() {
|
public Iterator<E> iterator() {
|
||||||
return new DynamicArrayIterator();
|
return new DynamicArrayIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private iterator class for the DynamicArray.
|
||||||
|
*/
|
||||||
private final class DynamicArrayIterator implements Iterator<E> {
|
private final class DynamicArrayIterator implements Iterator<E> {
|
||||||
|
|
||||||
private int cursor;
|
private int cursor;
|
||||||
private int expectedModCount;
|
private int expectedModCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new iterator for the dynamic array.
|
||||||
|
*/
|
||||||
DynamicArrayIterator() {
|
DynamicArrayIterator() {
|
||||||
this.expectedModCount = modCount;
|
this.expectedModCount = modCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there are more elements in the iteration.
|
||||||
|
*
|
||||||
|
* @return true if there are more elements, false otherwise
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
checkForComodification();
|
checkForComodification();
|
||||||
return cursor < size;
|
return cursor < size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next element in the iteration.
|
||||||
|
*
|
||||||
|
* @return the next element in the iteration
|
||||||
|
* @throws NoSuchElementException if the iteration has no more elements
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public E next() {
|
public E next() {
|
||||||
@ -177,22 +224,38 @@ public class DynamicArray<E> implements Iterable<E> {
|
|||||||
return (E) elements[cursor++];
|
return (E) elements[cursor++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last element returned by this iterator.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the next method has not yet been called, or the remove method has already been called after the last call to the next method
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (cursor <= 0) {
|
if (cursor <= 0) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException("Cannot remove element before calling next()");
|
||||||
}
|
}
|
||||||
checkForComodification();
|
checkForComodification();
|
||||||
DynamicArray.this.remove(--cursor);
|
DynamicArray.this.remove(--cursor);
|
||||||
expectedModCount = ++modCount;
|
expectedModCount = modCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for concurrent modifications to the array during iteration.
|
||||||
|
*
|
||||||
|
* @throws ConcurrentModificationException if the array has been modified structurally
|
||||||
|
*/
|
||||||
private void checkForComodification() {
|
private void checkForComodification() {
|
||||||
if (modCount != expectedModCount) {
|
if (modCount != expectedModCount) {
|
||||||
throw new ConcurrentModificationException();
|
throw new ConcurrentModificationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the given action for each remaining element in the iterator until all elements have been processed.
|
||||||
|
*
|
||||||
|
* @param action the action to be performed for each element
|
||||||
|
* @throws NullPointerException if the specified action is null
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void forEachRemaining(Consumer<? super E> action) {
|
public void forEachRemaining(Consumer<? super E> action) {
|
||||||
Objects.requireNonNull(action);
|
Objects.requireNonNull(action);
|
||||||
|
@ -24,6 +24,8 @@ public class DynamicArrayTest {
|
|||||||
public void testGetElement() {
|
public void testGetElement() {
|
||||||
array.add("Alice");
|
array.add("Alice");
|
||||||
array.add("Bob");
|
array.add("Bob");
|
||||||
|
array.add("Charlie");
|
||||||
|
array.add("David");
|
||||||
assertEquals("Bob", array.get(1));
|
assertEquals("Bob", array.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +33,7 @@ public class DynamicArrayTest {
|
|||||||
public void testGetInvalidIndex() {
|
public void testGetInvalidIndex() {
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> array.get(-1));
|
assertThrows(IndexOutOfBoundsException.class, () -> array.get(-1));
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> array.get(10));
|
assertThrows(IndexOutOfBoundsException.class, () -> array.get(10));
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> array.get(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user