Skip to content

Commit

Permalink
1. Динамический список на массиве. [#158 #179646]
Browse files Browse the repository at this point in the history
  • Loading branch information
Temzor committed Jul 2, 2024
1 parent 49a62a1 commit a66bf45
Show file tree
Hide file tree
Showing 3 changed files with 321 additions and 0 deletions.
78 changes: 78 additions & 0 deletions src/main/java/ru/j4j/collection/SimpleArrayList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ru.j4j.collection;

import java.util.*;

public class SimpleArrayList<T> implements SimpleList<T> {
private T[] container;
private int size;
private int modCount;

public SimpleArrayList(int capacity) {
container = (T[]) new Object[capacity];
}

private void grow() {
int newLength = container.length > 0 ? container.length * 2 : 1;
container = Arrays.copyOf(container, newLength);
}

@Override
public void add(T value) {
if (size == container.length) {
grow();
}
container[size++] = value;
modCount++;
}

@Override
public T remove(int index) {
T removedValue = get(index);
System.arraycopy(container, index + 1, container, index, size - index - 1);
size--;
modCount++;
return removedValue;
}

@Override
public T set(int index, T newValue) {
T changedValue = get(index);
container[index] = newValue;
return changedValue;
}

@Override
public T get(int index) {
Objects.checkIndex(index, size);
return container[index];
}

@Override
public int size() {
return size;
}

@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
public final int expectedModCount = modCount;

@Override
public boolean hasNext() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException("cannot be changed during iteration");
}
return index < size;
}

@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException("collection doesn't have the following element");
}
return container[index++];
}
};
}
}
13 changes: 13 additions & 0 deletions src/main/java/ru/j4j/collection/SimpleList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.j4j.collection;

public interface SimpleList<T> extends Iterable<T> {
void add(T value);

T remove(int index);

T set(int index, T newValue);

T get(int index);

int size();
}
230 changes: 230 additions & 0 deletions src/test/java/ru/j4j/collection/SimpleArrayListTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package ru.j4j.collection;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class SimpleArrayListTest {

private SimpleList<Integer> list;

@BeforeEach
void initData() {
list = new SimpleArrayList<>(3);
list.add(1);
list.add(2);
list.add(3);
}

@Test
void checkIterator() {
assertThat(list.size()).isEqualTo(3);
assertThat(list).hasSize(3);
}

@Test
void whenAddThenSizeIncrease() {
list.add(4);
assertThat(list.size()).isEqualTo(4);
}

@Test
void whenRemoveThenGetValueAndSizeDecrease() {
assertThat(list.remove(1)).isEqualTo(2);
assertThat(list.size()).isEqualTo(2);
}

@Test
void whenRemoveThenMustNotBeEmpty() {
list.remove(1);
assertThat(list.get(0)).isEqualTo(1);
assertThat(list.get(1)).isEqualTo(3);
}

@Test
void whenAddAndGetByCorrectIndex() {
list.add(4);
assertThat(list.get(3)).isEqualTo(4);
}

@Test
void whenGetByIncorrectIndexThenGetException() {
assertThatThrownBy(() -> list.get(5))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenAndAndGetByIncorrectIndexThenGetException() {
SimpleList<Integer> list = new SimpleArrayList<>(10);
list.add(5);
assertThatThrownBy(() -> list.get(5))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenRemoveByIncorrectIndexThenGetException() {
assertThatThrownBy(() -> list.remove(5))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenGetByNegateIndexThenGetException() {
assertThatThrownBy(() -> list.get(-2))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenSetByNegateIndexThenGetException() {
assertThatThrownBy(() -> list.set(-3, 22))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenRemoveByNegateIndexThenGetException() {
assertThatThrownBy(() -> list.remove(-1))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenRemoveByInvalidIndexThenGetException() {
list = new SimpleArrayList<>(3);
list.add(1);
assertThatThrownBy(() -> list.remove(1))
.isInstanceOf(IndexOutOfBoundsException.class);
}


@Test
void whenAddNullThenMustBeSameBehavior() {
list = new SimpleArrayList<>(3);
list.add(null);
list.add(null);
assertThat(list.size()).isEqualTo(2);
assertThat(list.get(0)).isNull();
assertThat(list.get(1)).isNull();
}

@Test
void whenSetThenGetOldValueAndSizeNotChanged() {
assertThat(list.set(1, 22)).isEqualTo(2);
assertThat(list.size()).isEqualTo(3);
}

@Test
void whenSetByIncorrectIndexThenGetException() {
assertThatThrownBy(() -> list.set(5, 22))
.isInstanceOf(IndexOutOfBoundsException.class);
}

@Test
void whenSetByInvalidIndexThenGetException() {
list = new SimpleArrayList<>(3);
list.add(1);
assertThatThrownBy(() -> list.set(2, 22))
.isInstanceOf(IndexOutOfBoundsException.class);
}


@Test
void whenGetIteratorFromEmptyListThenHasNextReturnFalse() {
list = new SimpleArrayList<>(5);
assertThat(list.iterator().hasNext()).isFalse();
}

@Test
void whenGetIteratorFromEmptyListThenNextThrowException() {
list = new SimpleArrayList<>(5);
assertThatThrownBy(list.iterator()::next)
.isInstanceOf(NoSuchElementException.class);
}

@Test
void whenGetIteratorTwiceThenStartAlwaysFromBeginning() {
assertThat(list.iterator().next()).isEqualTo(1);
assertThat(list.iterator().next()).isEqualTo(1);
}

@Test
void whenCheckIterator() {
Iterator<Integer> iterator = list.iterator();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo(1);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo(2);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo(3);
assertThat(iterator.hasNext()).isFalse();
}

@Test
void whenNoPlaceThenMustIncreaseCapacity() {
assertThat(list.size()).isEqualTo(3);
IntStream.range(3, 10).forEach(v -> list.add(v));
assertThat(list.size()).isEqualTo(10);
}

@Test
void whenIncreaseEmptyContainer() {
list = new SimpleArrayList<>(0);
assertThat(list.size()).isZero();
list.add(1);
assertThat(list.size()).isEqualTo(1);
assertThat(list.get(0)).isEqualTo(1);
}

@Test
void whenAddAfterGetIteratorHasNextThenMustBeException() {
Iterator<Integer> iterator = list.iterator();
assertThat(iterator.hasNext()).isTrue();
list.add(4);
assertThatThrownBy(iterator::hasNext)
.isInstanceOf(ConcurrentModificationException.class);
}

@Test
void whenRemoveAfterGetIteratorHasNextThenMustBeException() {
Iterator<Integer> iterator = list.iterator();
assertThat(iterator.hasNext()).isTrue();
list.remove(0);
assertThatThrownBy(iterator::hasNext)
.isInstanceOf(ConcurrentModificationException.class);
}

@Test
void whenSetAfterGetIteratorHasNextThenMustBeOk() {
Iterator<Integer> iterator = list.iterator();
assertThat(iterator.hasNext()).isTrue();
list.set(0, 22);
assertThat(iterator.hasNext()).isTrue();
}

@Test
void whenAddAfterGetIteratorThenMustBeException() {
Iterator<Integer> iterator = list.iterator();
list.add(4);
assertThatThrownBy(iterator::next)
.isInstanceOf(ConcurrentModificationException.class);
}

@Test
void whenRemoveAfterGetIteratorThenMustBeException() {
Iterator<Integer> iterator = list.iterator();
list.remove(0);
assertThatThrownBy(iterator::next)
.isInstanceOf(ConcurrentModificationException.class);
}

@Test
void whenSetAfterGetIteratorThenMustBeOk() {
Iterator<Integer> iterator = list.iterator();
list.set(0, 22);
assertThat(iterator.next()).isEqualTo(22);
}
}

0 comments on commit a66bf45

Please sign in to comment.