diff --git a/MyTreeSet/.gitignore b/MyTreeSet/.gitignore new file mode 100644 index 0000000..345e61a --- /dev/null +++ b/MyTreeSet/.gitignore @@ -0,0 +1,49 @@ +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties diff --git a/MyTreeSet/.idea/compiler.xml b/MyTreeSet/.idea/compiler.xml new file mode 100644 index 0000000..efede30 --- /dev/null +++ b/MyTreeSet/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTreeSet/.idea/misc.xml b/MyTreeSet/.idea/misc.xml new file mode 100644 index 0000000..e8942bd --- /dev/null +++ b/MyTreeSet/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/MyTreeSet/.idea/modules.xml b/MyTreeSet/.idea/modules.xml new file mode 100644 index 0000000..0f5d373 --- /dev/null +++ b/MyTreeSet/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/MyTreeSet/MyTreeSet.iml b/MyTreeSet/MyTreeSet.iml new file mode 100644 index 0000000..57f498f --- /dev/null +++ b/MyTreeSet/MyTreeSet.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTreeSet/pom.xml b/MyTreeSet/pom.xml new file mode 100644 index 0000000..00d906d --- /dev/null +++ b/MyTreeSet/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + ru,spbau.mit.kazakov.MyTreeSet + MyTreeSet + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + junit + junit + 4.8 + + + org.jetbrains + annotations + 13.0 + + + + \ No newline at end of file diff --git a/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/HisTreeSet.java b/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/HisTreeSet.java new file mode 100644 index 0000000..2b2c8fe --- /dev/null +++ b/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/HisTreeSet.java @@ -0,0 +1,35 @@ +package ru.spabu.mit.kazakov.TreeSet; + +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; + +public interface HisTreeSet extends Set { + + /** {@link TreeSet#descendingIterator()} **/ + Iterator descendingIterator(); + + /** {@link TreeSet#descendingSet()} **/ + HisTreeSet descendingSet(); + + + /** {@link TreeSet#first()} **/ + E first(); + + /** {@link TreeSet#last()} **/ + E last(); + + + /** {@link TreeSet#lower(E)} **/ + E lower(E e); + + /** {@link TreeSet#floor(E)} **/ + E floor(E e); + + + /** {@link TreeSet#ceiling(E)} **/ + E ceiling(E e); + + /** {@link TreeSet#higher(E)} **/ + E higher(E e); +} diff --git a/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/MyTreeSet.java b/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/MyTreeSet.java new file mode 100644 index 0000000..08f7a34 --- /dev/null +++ b/MyTreeSet/src/main/java/ru/spabu/mit/kazakov/TreeSet/MyTreeSet.java @@ -0,0 +1,464 @@ +package ru.spabu.mit.kazakov.TreeSet; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.AbstractSet; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A generic set implemented using binary search tree. + * + * @param type of stored value + */ +public class MyTreeSet extends AbstractSet implements HisTreeSet { + private Comparator comparator; + private int size = 0; + private Node root = null; + private boolean reverse = false; + + /** + * Makes new myTreeSet containing values from specified myTreeSet, but with reversed order view of the values. + * + * @param originalSet specified myTreeSet + */ + private MyTreeSet(@NotNull MyTreeSet originalSet) { + root = originalSet.root; + size = originalSet.size; + comparator = originalSet.comparator; + reverse = !originalSet.reverse; + } + + /** + * Returns Node storing specified value. + * + * @param value specified value + * @return found Node if there is such Node, and null otherwise. + */ + @Nullable + private Node find(@NotNull E value) { + Node current = root; + + while (current != null) { + int compareResult = comparator.compare(current.value, value); + if (compareResult == 0) { + return current; + } else if (compareResult > 0) { + current = current.left; + } else { + current = current.right; + } + } + + return null; + } + + /** + * Returns lowest value. + * + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderFirst() { + Node current = root; + if (current == null) { + return null; + } + + while (current.left != null) { + current = current.left; + } + + return current.value; + } + + /** + * Returns highest value. + * + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderLast() { + Node current = root; + if (current == null) { + return null; + } + + while (current.right != null) { + current = current.right; + } + + return current.value; + } + + /** + * Returns the greatest value in this set strictly less than the specified value. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderLower(@NotNull E value) { + Node current = root; + if (current == null) { + return null; + } + E answer = null; + + while (current != null) { + int compareResult = comparator.compare(current.value, value); + if (compareResult >= 0) { + current = current.left; + } else { + answer = current.value; + current = current.right; + } + } + + return answer; + } + + /** + * Returns the greatest value in this set less than or equal to the specified value, + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderFloor(@NotNull E value) { + Node found = find(value); + return found != null ? found.value : normalOrderLower(value); + } + + /** + * Returns the least value in this set greater than or equal to the specified value. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderCeiling(@NotNull E value) { + Node found = find(value); + return found != null ? found.value : normalOrderHigher(value); + } + + /** + * Returns the least value in this set strictly greater than the given value, + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + private E normalOrderHigher(@NotNull E value) { + Node current = root; + E answer = null; + + while (current != null) { + int compareResult = comparator.compare(current.value, value); + if (compareResult <= 0) { + current = current.right; + } else { + answer = current.value; + current = current.left; + } + } + + return answer; + } + + /** + * Initializes comparator for values ordering by specified comparator. + * + * @param comparator specified comparator + */ + public MyTreeSet(@NotNull Comparator comparator) { + this.comparator = comparator; + } + + /** + * Initializes comparator for values ordering using value's comparability, + * therefore generic type must implements Comparable interface. + */ + public MyTreeSet() { + comparator = (o1, o2) -> ((Comparable) o1).compareTo(o2); + } + + /** + * Checks if there is a value equals to specified value. + * + * @param value to check + * @return true if there is such value, and false otherwise + */ + @Override + public boolean contains(@NotNull Object value) { + return find((E) value) != null; + } + + /** + * Adds new Node storing specified value to the tree. + * + * @param value to add + * @return false if there was specified value, and true otherwise + */ + @Override + public boolean add(@NotNull E value) { + if (contains(value)) { + return false; + } + if (root == null) { + root = new Node(value); + size = 1; + return true; + } + + Node current = root; + Node parent = null; + while (current != null) { + parent = current; + int compareResult = comparator.compare(current.value, value); + if (compareResult > 0) { + current = current.left; + } else if (compareResult < 0) { + current = current.right; + } + + } + + int compareResult = comparator.compare(parent.value, value); + if (compareResult < 0) { + parent.right = new Node(value); + } else if (compareResult > 0) { + parent.left = new Node(value); + } + + size++; + return true; + } + + /** + * Removes Node storing specified value from tree. + * + * @param value to remove + * @return true if there was specified value, and false otherwise + */ + @Override + public boolean remove(@NotNull Object value) { + if (!contains(value)) { + return false; + } + size--; + + Node current = root; + Node parent = null; + int compareResult; + while ((compareResult = comparator.compare(current.value, (E) value)) != 0) { + parent = current; + if (compareResult > 0) { + current = current.left; + } else { + current = current.right; + } + } + + boolean isLeftChild = parent != null && parent.left == current; + if (parent != null) { + if (current.left == null) { + if (isLeftChild) { + parent.left = current.right; + return true; + } else { + parent.right = current.right; + return true; + } + } else if (current.right == null) { + if (isLeftChild) { + parent.left = current.left; + return true; + } else { + parent.right = current.left; + return true; + } + } + } else { + if (current.left == null) { + root = current.right; + return true; + } else if (current.right == null) { + root = current.left; + return true; + } + } + + E nextValue = normalOrderHigher(current.value); + remove(nextValue); + current.value = nextValue; + + return true; + } + + /** + * Returns an iterator over the values in this set in descending order. + */ + @NotNull + public Iterator descendingIterator() { + return descendingSet().iterator(); + } + + /** + * Returns a reverse order view of the values contained in this set. + */ + public MyTreeSet descendingSet() { + return new MyTreeSet<>(this); + } + + /** + * Returns lowest value if order isn't reversed, and highest value otherwise. + * + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E first() { + if (reverse) { + return normalOrderLast(); + } else { + return normalOrderFirst(); + } + } + + /** + * Returns highest value if order isn't reversed, and lowest value otherwise. + * + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E last() { + if (reverse) { + return normalOrderFirst(); + } else { + return normalOrderLast(); + } + } + + /** + * Returns the greatest value in this set strictly less than the specified value if order isn't reversed, and + * the least value in this set strictly greater than the specified value otherwise. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E lower(@NotNull E value) { + if (reverse) { + return normalOrderHigher(value); + } else { + return normalOrderLower(value); + } + } + + /** + * Returns the greatest value in this set less than or equal to the specified value if order isn't reversed, and + * the least value in this set greater than or equal to the specified value otherwise. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E floor(@NotNull E value) { + if (reverse) { + return normalOrderCeiling(value); + } else { + return normalOrderFloor(value); + } + } + + /** + * Returns the least value in this set greater than or equal to the specified value if order isn't reversed, and + * the greatest value in this set less than or equal to the specified value otherwise. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E ceiling(@NotNull E value) { + if (reverse) { + return normalOrderLower(value); + } else { + return normalOrderCeiling(value); + } + } + + /** + * Returns the least value in this set strictly greater than the given value if order isn't reversed, and + * the greatest value in this set strictly less than the specified value otherwise. + * + * @param value specified value + * @return found value if there is such value, and null otherwise + */ + @Nullable + public E higher(@NotNull E value) { + if (reverse) { + return normalOrderLower(value); + } else { + return normalOrderHigher(value); + } + } + + /** + * Returns an iterator over the values in this set. + */ + @NotNull + public Iterator iterator() { + return new MyTreeSetIterator(); + } + + /** + * Returns number of stored values in the tree. + */ + public int size() { + return size; + } + + /** + * Node for binary search tree. Stores left, right children and value. + */ + private class Node { + private Node left = null; + private Node right = null; + private E value; + + /** + * Initializes stored value with specified value. + * + * @param value specified value + */ + private Node(@NotNull E value) { + this.value = value; + } + + } + + /** + * Iterator for ru.spabu.mit.kazakov.TreeSet.MyTreeSet. + */ + private class MyTreeSetIterator implements Iterator { + private E next = first(); + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public E next() { + if (next == null) { + throw new NoSuchElementException(); + } + + E prev = next; + next = higher(next); + return prev; + } + } +} diff --git a/MyTreeSet/src/test/java/MyTreeSetTest.java b/MyTreeSet/src/test/java/MyTreeSetTest.java new file mode 100644 index 0000000..acc6aaa --- /dev/null +++ b/MyTreeSet/src/test/java/MyTreeSetTest.java @@ -0,0 +1,395 @@ +import org.junit.Test; +import ru.spabu.mit.kazakov.TreeSet.MyTreeSet; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +import static org.junit.Assert.*; + +public class MyTreeSetTest { + @Test + public void testConstructor() { + new MyTreeSet(); + } + + @Test + public void testConstructorWithComparator() { + new MyTreeSet((o1, o2) -> -1 * o1.compareTo(o2)); + } + + @Test + public void testAddReturnTrue() { + MyTreeSet mySet = new MyTreeSet<>(); + assertTrue(mySet.add(1L)); + } + + @Test + public void testAddReturnFalse() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(1L); + + assertFalse(mySet.add(1L)); + } + + @Test + public void testAdd() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(17L); + mySet.add(13L); + mySet.add(2L); + + assertArrayEquals(new Long[]{2L, 13L, 17L}, mySet.toArray()); + } + + @Test + public void testAddTheSame() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(17L); + mySet.add(13L); + mySet.add(2L); + mySet.add(13L); + + assertArrayEquals(new Long[]{2L, 13L, 17L}, mySet.toArray()); + } + + @Test + public void testAddRandom() { + MyTreeSet mySet = new MyTreeSet<>(); + TreeSet random = new TreeSet<>(); + + for (int i = 0; i < 100; i++) { + Integer valueToAdd = ThreadLocalRandom.current().nextInt(0, 30); + random.add(valueToAdd); + mySet.add(valueToAdd); + } + + assertArrayEquals(random.toArray(), mySet.toArray()); + } + + @Test + public void testRemoveReturnTrue() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.add((char) 1); + + assertTrue(mySet.remove((char) 1)); + } + + @Test + public void testRemoveReturnFalse() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.add((char) 1); + + assertFalse(mySet.remove((char) 2)); + } + + @Test + public void testRemove() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add('a'); + mySet.add('z'); + mySet.add('v'); + mySet.add('t'); + mySet.remove('t'); + mySet.remove('a'); + + assertArrayEquals(new Character[]{'v', 'z'}, mySet.toArray()); + } + + @Test + public void testRemoveTheSame() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add('a'); + mySet.add('z'); + mySet.add('v'); + mySet.add('t'); + mySet.remove('t'); + mySet.remove('a'); + mySet.remove('t'); + + assertArrayEquals(new Character[]{'v', 'z'}, mySet.toArray()); + } + + @Test + public void testSizeEmpty() { + assertEquals(0, new MyTreeSet().size()); + } + + @Test + public void testSizeAdd() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(5); + mySet.add(2); + + assertEquals(2, mySet.size()); + } + + @Test + public void testSizeAddTheSame() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(2); + mySet.add(2); + + assertEquals(1, mySet.size()); + } + + @Test + public void testSizeRemove() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(5); + mySet.add(2); + mySet.remove(2); + + assertEquals(1, mySet.size()); + } + + @Test + public void testSizeRemoveTheSame() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add(5); + mySet.add(2); + mySet.remove(2); + mySet.remove(2); + + assertEquals(1, mySet.size()); + } + + @Test + public void testSizeOneHundred() { + MyTreeSet mySet = new MyTreeSet<>(); + for (int i = 0; i < 100; i++) { + mySet.add(i); + } + + assertEquals(100, mySet.size()); + } + + @Test + public void testContainsNotExisting() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add((byte) 1); + + assertFalse(mySet.contains((byte) 2)); + } + + @Test + public void testContainsAdd() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add((byte) 55); + + assertTrue(mySet.contains((byte) 55)); + } + + @Test + public void testContainsRemove() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.add((byte) 111); + mySet.remove((byte) 111); + + assertFalse(mySet.contains((byte) 111)); + } + + @Test + public void testFirstEmptySet() { + assertNull(new MyTreeSet((o1, o2) -> -1 * o1.compareTo(o2)).first()); + } + + @Test + public void testFirst() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.addAll(Arrays.asList((short) 100, (short) -2, (short) -33, (short) 4)); + assertEquals(100, mySet.first().shortValue()); + } + + @Test + public void testFirstDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.addAll(Arrays.asList((short) 100, (short) -2, (short) -33, (short) 4)); + assertEquals(-33, mySet.descendingSet().first().shortValue()); + } + + @Test + public void testLastEmptySet() { + assertNull(new MyTreeSet((o1, o2) -> -1 * o1.compareTo(o2)).last()); + } + + @Test + public void testLast() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.addAll(Arrays.asList((short) 100, (short) -2, (short) -33, (short) 4)); + assertEquals(-33, mySet.last().shortValue()); + } + + @Test + public void testLastDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>((o1, o2) -> -1 * o1.compareTo(o2)); + mySet.addAll(Arrays.asList((short) 100, (short) -2, (short) -33, (short) 4)); + assertEquals(100, mySet.descendingSet().last().shortValue()); + } + + @Test + public void testEmptyHigher() { + assertNull(new MyTreeSet().higher((short) 15)); + } + + @Test + public void testNotExistingHigher() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.higher((short) 15)); + } + + @Test + public void testNotExistingHigherDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.descendingSet().higher((short) 1)); + } + + @Test + public void testHigher() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(10, mySet.higher((short) 3).shortValue()); + } + + @Test + public void testHigherDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(3, mySet.descendingSet().higher((short) 10).shortValue()); + } + + @Test + public void testEmptyLower() { + assertNull(new MyTreeSet().lower((short) 15)); + } + + @Test + public void testNotExistingLower() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.lower((short) 1)); + } + + @Test + public void testNotExistingLowerDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.descendingSet().lower((short) 15)); + } + + @Test + public void testLower() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(1, mySet.lower((short) 2).shortValue()); + } + + @Test + public void testLowerDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(10, mySet.descendingSet().lower((short) 4).shortValue()); + } + + @Test + public void testEmptyFloor() { + assertNull(new MyTreeSet<>().floor((short) 15)); + } + + @Test + public void testNotExistingFloor() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.floor((short) 0)); + } + + @Test + public void testNotExistingFloorDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.descendingSet().floor((short) 17)); + } + + @Test + public void testFloor() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(15, mySet.floor((short) 15).shortValue()); + } + + @Test + public void testFloorDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(10, mySet.descendingSet().lower((short) 4).shortValue()); + } + + @Test + public void testEmptyCeiling() { + assertNull(new MyTreeSet<>().ceiling((short) 15)); + } + + @Test + public void testNotExistingCeiling() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.ceiling((short) 100)); + } + + @Test + public void testNotExistingCeilingDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertNull(mySet.descendingSet().ceiling((short) -17)); + } + + @Test + public void testCeiling() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(15, mySet.ceiling((short) 15).shortValue()); + } + + @Test + public void testCeilingDescendingSet() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 15, (short) 10)); + assertEquals(3, mySet.descendingSet().ceiling((short) 4).shortValue()); + } + + @Test(expected = NoSuchElementException.class) + public void testIteratorThrowsNoSuchElementException() { + Iterator iterator = new MyTreeSet().iterator(); + iterator.next(); + } + + @Test + public void testIterator() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 2, (short) 0)); + Iterator iterator = mySet.iterator(); + + for (byte i = 0; i < 4; i++) { + assertTrue(iterator.hasNext()); + assertEquals(i, iterator.next().byteValue()); + } + + assertFalse(iterator.hasNext()); + } + + @Test + public void testDescendingIterator() { + MyTreeSet mySet = new MyTreeSet<>(); + mySet.addAll(Arrays.asList((short) 1, (short) 3, (short) 2, (short) 0)); + Iterator iterator = mySet.descendingIterator(); + + for (byte i = 3; i >= 0; i--) { + assertTrue(iterator.hasNext()); + assertEquals(i, iterator.next().byteValue()); + } + + assertFalse(iterator.hasNext()); + } + +} \ No newline at end of file