From 28275d2e530e8e3e346426967d67f7f92ea50e9d Mon Sep 17 00:00:00 2001 From: Milena Hakobyan Date: Tue, 27 May 2025 13:29:30 +0400 Subject: [PATCH 1/2] Complete Generics and Functional Programming tasks Generics: - Completed tasks from: - 1-3-0 (Hello Generics) - 1-3-1 (Crazy Generics) - 1-3-2 (Heterogeneous Max Holder) Functional Programming & Streams: - Completed tasks from: - 5-0-1 (Lambda Functions Map) - 5-0-2 (Sum of Squares) - 5-1-1 (Crazy Lambdas) - 5-2-1 (Crazy Streams) - 5-3-1 (Crazy Optionals) - 5-4-1 (Fun Prime Numbers) Other: - Finished RandomFieldComparator covering the Reflection topic (from Optionals repo) --- .gitignore | 9 ++ .../main/java/com/bobocode/basics/Box.java | 10 +- .../java/com/bobocode/basics/BoxDemoApp.java | 5 +- .../com/bobocode/basics/CrazyGenerics.java | 117 ++++++++++++------ .../com/bobocode/basics/util/BaseEntity.java | 16 +++ .../basics/HeterogeneousMaxHolder.java | 38 +++++- .../bobocode/se/RandomFieldComparator.java | 42 ++++++- .../main/java/com/bobocode/fp/Functions.java | 7 +- .../java/com/bobocode/fp/SumOfSquares.java | 10 +- .../java/com/bobocode/fp/CrazyLambdas.java | 58 ++++++--- .../java/com/bobocode/fp/CrazyStreams.java | 88 ++++++++++--- .../java/com/bobocode/fp/CrazyOptionals.java | 57 ++++++--- .../java/com/bobocode/fp/PrimeNumbers.java | 37 ++++-- .../main/java/com/bobocode/model/Account.java | 36 ++++++ 14 files changed, 410 insertions(+), 120 deletions(-) diff --git a/.gitignore b/.gitignore index 9cdb1dbb9..47b8f5fd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ .idea **/*.iml **/target +.DS_Store +0-0-intro/ +1-0-java-basics/1-5-0-hello-annotations/ +2-0-data-structures-and-algorithms/ +3-0-java-core/3-6-1-file-reader/ +3-0-java-core/3-6-2-file-stats/ +3-0-java-core/3-6-3-crazy-regex/ +4-0-object-oriented-programming/ +6-0-test-driven-development/ \ No newline at end of file diff --git a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java index 5a2d860ee..180603a28 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java @@ -7,18 +7,18 @@ *

* todo: refactor this class so it uses generic type "T" and run {@link com.bobocode.basics.BoxTest} to verify it */ -public class Box { - private Object value; +public class Box { + private T value; - public Box(Object value) { + public Box(T value) { this.value = value; } - public Object getValue() { + public T getValue() { return value; } - public void setValue(Object value) { + public void setValue(T value) { this.value = value; } } diff --git a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java index bc12174ee..5bdae783b 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java @@ -9,11 +9,12 @@ */ public class BoxDemoApp { public static void main(String[] args) { - Box intBox = new Box(123); - Box intBox2 = new Box(321); + Box intBox = new Box(123); + Box intBox2 = new Box(321); System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); intBox.setValue(222); + // must not compile!! intBox.setValue("abc"); // this should not be allowed // the following code will compile, but will throw runtime exception System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java index 751d5899f..c1aca7535 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java @@ -1,14 +1,11 @@ package com.bobocode.basics; import com.bobocode.basics.util.BaseEntity; -import com.bobocode.util.ExerciseNotCompletedException; import lombok.Data; import java.io.Serializable; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.function.Predicate; /** * {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated @@ -33,8 +30,8 @@ public class CrazyGenerics { * @param – value type */ @Data - public static class Sourced { // todo: refactor class to introduce type parameter and make value generic - private Object value; + public static class Sourced { // todo: refactor class to introduce type parameter and make value generic + private T value; private String source; } @@ -45,11 +42,17 @@ public static class Sourced { // todo: refactor class to introduce type paramete * @param – actual, min and max type */ @Data - public static class Limited { + public static class Limited { // todo: refactor class to introduce type param bounded by number and make fields generic numbers - private final Object actual; - private final Object min; - private final Object max; + private final T actual; + private final T min; + private final T max; + + public Limited(T actual, T min, T max) { + this.actual = actual; + this.min = min; + this.max = max; + } } /** @@ -59,8 +62,8 @@ public static class Limited { * @param – source object type * @param - converted result type */ - public interface Converter { // todo: introduce type parameters - // todo: add convert method + public interface Converter { // todo: introduce type parameters + R convert(T param); } /** @@ -70,10 +73,10 @@ public interface Converter { // todo: introduce type parameters * * @param – value type */ - public static class MaxHolder { // todo: refactor class to make it generic - private Object max; + public static class MaxHolder> { // todo: refactor class to make it generic + private T max; - public MaxHolder(Object max) { + public MaxHolder(T max) { this.max = max; } @@ -82,11 +85,11 @@ public MaxHolder(Object max) { * * @param val a new value */ - public void put(Object val) { - throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method + public void put(T val) { + max = (max == null || val.compareTo(max) > 0) ? val : max; } - public Object getMax() { + public T getMax() { return max; } } @@ -97,8 +100,8 @@ public Object getMax() { * * @param – the type of objects that can be processed */ - interface StrictProcessor { // todo: make it generic - void process(Object obj); + interface StrictProcessor> { // todo: make it generic + void process(T obj); } /** @@ -108,10 +111,10 @@ interface StrictProcessor { // todo: make it generic * @param – a type of the entity that should be a subclass of {@link BaseEntity} * @param – a type of any collection */ - interface CollectionRepository { // todo: update interface according to the javadoc - void save(Object entity); + interface CollectionRepository> { // todo: update interface according to the javadoc + void save(T entity); - Collection getEntityCollection(); + C getEntityCollection(); } /** @@ -120,7 +123,7 @@ interface CollectionRepository { // todo: update interface according to the java * * @param – a type of the entity that should be a subclass of {@link BaseEntity} */ - interface ListRepository { // todo: update interface according to the javadoc + interface ListRepository extends CollectionRepository> { // todo: update interface according to the javadoc } /** @@ -133,7 +136,11 @@ interface ListRepository { // todo: update interface according to the javadoc * * @param a type of collection elements */ - interface ComparableCollection { // todo: refactor it to make generic and provide a default impl of compareTo + // todo: refactor it to make generic and provide a default impl of compareTo + interface ComparableCollection extends Collection, Comparable> { + default int compareTo(Collection other) { + return Integer.compare(this.size(), other.size()); + } } /** @@ -147,9 +154,8 @@ static class CollectionUtil { * * @param list */ - public static void print(List list) { - // todo: refactor it so the list of any type can be printed, not only integers - list.forEach(element -> System.out.println(" – " + element)); + public static void print(List list) { + list.forEach(element -> System.out.println(" – " + element)); // todo: refactor it so the list of any type can be printed, not only integers } /** @@ -160,8 +166,11 @@ public static void print(List list) { * @param entities provided collection of entities * @return true if at least one of the elements has null id */ - public static boolean hasNewEntities(Collection entities) { - throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method + public static boolean hasNewEntities(Collection entities) { + for (BaseEntity entity : entities) + if (entity.getUuid() == null) + return true; + return false; } /** @@ -173,8 +182,12 @@ public static boolean hasNewEntities(Collection entities) { * @param validationPredicate criteria for validation * @return true if all entities fit validation criteria */ - public static boolean isValidCollection() { - throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic + public static boolean isValidCollection(Collection entities, Predicate validationPredicate) { + for (BaseEntity entity : entities) { + if (!validationPredicate.test(entity)) + return false; + } + return true; } /** @@ -187,8 +200,16 @@ public static boolean isValidCollection() { * @param entity type * @return true if entities list contains target entity more than once */ - public static boolean hasDuplicates() { - throw new ExerciseNotCompletedException(); // todo: update method signature and implement it + public static boolean hasDuplicates(Collection entities, T targetEntity) { + // todo: update method signature and implement it + int count = 0; + for (BaseEntity entity : entities) { + if (entity.getUuid().equals(targetEntity.getUuid())) + count++; + if (count > 1) + return true; + } + return false; } /** @@ -201,6 +222,19 @@ public static boolean hasDuplicates() { * @return optional max value */ // todo: create a method and implement its logic manually without using util method from JDK + public static Optional findMax(Iterable elements, Comparator comparator) { + Iterator it = elements.iterator(); + if (it.hasNext()) { + T max = it.next(); + while (it.hasNext()) { + T cur = it.next(); + if (comparator.compare(cur, max) > 0) + max = cur; + } + return Optional.of(max); + } + return Optional.empty(); + } /** * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the @@ -214,7 +248,10 @@ public static boolean hasDuplicates() { * @param entity type * @return an entity from the given collection that has the max createdOn value */ - // todo: create a method according to JavaDoc and implement it using previous method + public static T findMostRecentlyCreatedEntity(Collection entities) { + return findMax(entities, CREATED_ON_COMPARATOR) + .orElseThrow(java.util.NoSuchElementException::new); + } /** * An util method that allows to swap two elements of any list. It changes the list so the element with the index @@ -228,7 +265,13 @@ public static boolean hasDuplicates() { public static void swap(List elements, int i, int j) { Objects.checkIndex(i, elements.size()); Objects.checkIndex(j, elements.size()); - throw new ExerciseNotCompletedException(); // todo: complete method implementation + swapHelper(elements, i, j); + } + + private static void swapHelper(List list, int i, int j) { + T temp = list.get(i); + list.set(i, list.get(j)); + list.set(j, temp); } } diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java index f961ab7a5..10e621415 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java @@ -18,4 +18,20 @@ public BaseEntity(UUID uuid) { this.uuid = uuid; this.createdOn = LocalDateTime.now(); } + + public UUID getUuid() { + return uuid; + } + + public void setUuid(UUID uuid) { + this.uuid = uuid; + } + + public LocalDateTime getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(LocalDateTime createdOn) { + this.createdOn = createdOn; + } } diff --git a/1-0-java-basics/1-3-2-heterogeneous-max-holder/src/main/java/com/bobocode/basics/HeterogeneousMaxHolder.java b/1-0-java-basics/1-3-2-heterogeneous-max-holder/src/main/java/com/bobocode/basics/HeterogeneousMaxHolder.java index 9ef839910..60c22ac27 100644 --- a/1-0-java-basics/1-3-2-heterogeneous-max-holder/src/main/java/com/bobocode/basics/HeterogeneousMaxHolder.java +++ b/1-0-java-basics/1-3-2-heterogeneous-max-holder/src/main/java/com/bobocode/basics/HeterogeneousMaxHolder.java @@ -1,6 +1,6 @@ package com.bobocode.basics; -import java.util.Map; +import java.util.*; /** * {@link HeterogeneousMaxHolder} is a multi-type container that holds maximum values per each type. It's kind of a @@ -15,6 +15,7 @@ * @author Taras Boychuk */ public class HeterogeneousMaxHolder { + Map, Object> maxValues = new HashMap<>(); /** * A method put stores a provided value by its type, if the value is greater than the current maximum. In other words, the logic @@ -31,6 +32,19 @@ public class HeterogeneousMaxHolder { * @return a smaller value among the provided value and the current maximum */ // todo: implement a method according to javadoc + public > T put(Class key, T value) { + T cur = (T) maxValues.get(key); + if (cur == null) { + maxValues.put(key, value); + return null; + } + if (cur.compareTo(value) < 0) { + maxValues.put(key, value); + return cur; + } + return value; + } + /** * An overloaded method put implements the same logic using a custom comparator. A given comparator is wrapped with @@ -45,6 +59,23 @@ public class HeterogeneousMaxHolder { * @return a smaller value among the provided value and the current maximum */ // todo: implement a method according to javadoc + public T put(Class key, T value, Comparator comparator) { + Objects.requireNonNull(key); + Objects.requireNonNull(value); + Objects.requireNonNull(comparator); + + comparator = Comparator.nullsFirst(comparator); + + T currentMax = (T) maxValues.get(key); + + if (comparator.compare(currentMax, value) < 0) { + maxValues.put(key, (value)); + return currentMax; + } else { + return value; + } + } + /** * A method getMax returns a max value by the given type. If no value is stored by this type, then it returns null. @@ -54,4 +85,9 @@ public class HeterogeneousMaxHolder { * @return current max value or null */ // todo: implement a method according to javadoc + public T getMax(Class key) { + T value = (T) maxValues.get(key); + return (value == null) ? null : value; + } + } diff --git a/3-0-java-core/3-6-4-random-field-comparator/src/main/java/com/bobocode/se/RandomFieldComparator.java b/3-0-java-core/3-6-4-random-field-comparator/src/main/java/com/bobocode/se/RandomFieldComparator.java index 760989875..be1acd01f 100644 --- a/3-0-java-core/3-6-4-random-field-comparator/src/main/java/com/bobocode/se/RandomFieldComparator.java +++ b/3-0-java-core/3-6-4-random-field-comparator/src/main/java/com/bobocode/se/RandomFieldComparator.java @@ -1,7 +1,7 @@ package com.bobocode.se; -import com.bobocode.util.ExerciseNotCompletedException; -import java.util.Comparator; +import java.lang.reflect.Field; +import java.util.*; /** * A generic comparator that is comparing a random field of the given class. The field is either primitive or @@ -17,11 +17,23 @@ * @author Stanislav Zabramnyi */ public class RandomFieldComparator implements Comparator { + private final Field chosenField; public RandomFieldComparator(Class targetType) { - throw new ExerciseNotCompletedException(); // todo: implement this constructor; + Field[] fields = targetType.getDeclaredFields(); + + List candidates = Arrays.stream(fields) + .filter(field -> field.getType().isPrimitive() || Comparable.class.isAssignableFrom(field.getType())) + .toList(); + + if (candidates.isEmpty()) { + throw new IllegalArgumentException("No comparable field found"); + } + + chosenField = candidates.get(new Random().nextInt(candidates.size())); } + /** * Compares two objects of the class T by the value of the field that was randomly chosen. It allows null values * for the fields, and it treats null value greater than a non-null value. @@ -34,14 +46,31 @@ public RandomFieldComparator(Class targetType) { */ @Override public int compare(T o1, T o2) { - throw new ExerciseNotCompletedException(); // todo: implement this method; + try { + chosenField.setAccessible(true); + Object value1 = chosenField.get(o1); + Object value2 = chosenField.get(o2); + + + //nulls are considered greater, so they go last + if (value1 == null && value2 == null) return 0; + if (value1 == null) return 1; + if (value2 == null) return -1; + + @SuppressWarnings("unchecked") + Comparable comp1 = (Comparable) value1; + return comp1.compareTo(value2); + } catch (IllegalAccessException e) { + throw new RuntimeException("Cannot access field for comparison", e); + } + } /** * Returns the name of the randomly-chosen comparing field. */ public String getComparingFieldName() { - throw new ExerciseNotCompletedException(); // todo: implement this method; + return chosenField.getName(); // todo: implement this method; } /** @@ -52,6 +81,7 @@ public String getComparingFieldName() { */ @Override public String toString() { - throw new ExerciseNotCompletedException(); // todo: implement this method; + return String.format("Random field comparator of class '%s' is comparing '%s'", + chosenField.getDeclaringClass().getSimpleName(), chosenField.getName()); // todo: implement this method; } } diff --git a/5-0-functional-programming/5-0-1-lambda-functions-map/src/main/java/com/bobocode/fp/Functions.java b/5-0-functional-programming/5-0-1-lambda-functions-map/src/main/java/com/bobocode/fp/Functions.java index a1eed08d4..85242413f 100644 --- a/5-0-functional-programming/5-0-1-lambda-functions-map/src/main/java/com/bobocode/fp/Functions.java +++ b/5-0-functional-programming/5-0-1-lambda-functions-map/src/main/java/com/bobocode/fp/Functions.java @@ -6,7 +6,7 @@ *

* TODO: implement a method and verify it by running {@link FunctionsTest} *

- * TODO: if you find this exercise valuable and you want to get more like it, + * TODO: if you find this exercise valuable and you want to get more like it, * please support us on Patreon * * @author Taras Boychuk @@ -29,6 +29,11 @@ public static FunctionMap intFunctionMap() { FunctionMap intFunctionMap = new FunctionMap<>(); // todo: according to the javadoc add functions using lambda expression + intFunctionMap.addFunction("abs", x -> Math.abs(x)); + intFunctionMap.addFunction("sgn", x -> Integer.compare(x, 0)); + intFunctionMap.addFunction("increment", x -> x + 1); + intFunctionMap.addFunction("decrement", x -> x - 1); + intFunctionMap.addFunction("square", x -> x * x); return intFunctionMap; } diff --git a/5-0-functional-programming/5-0-2-stream-sum-of-squares/src/main/java/com/bobocode/fp/SumOfSquares.java b/5-0-functional-programming/5-0-2-stream-sum-of-squares/src/main/java/com/bobocode/fp/SumOfSquares.java index b043454d1..50fc2be60 100644 --- a/5-0-functional-programming/5-0-2-stream-sum-of-squares/src/main/java/com/bobocode/fp/SumOfSquares.java +++ b/5-0-functional-programming/5-0-2-stream-sum-of-squares/src/main/java/com/bobocode/fp/SumOfSquares.java @@ -2,6 +2,8 @@ import com.bobocode.fp.exception.InvalidRangeException; +import java.util.stream.IntStream; + /** * This class allow to calculate a sum of squares of integer number in a certain range. It was implemented using * OO approach. Your job is to refactor it using functional approach. E.g. avoid using mutable variables @@ -26,10 +28,8 @@ static int calculateSumOfSquaresInRange(int startInclusive, int endInclusive) { } // todo: refactor using functional approach – instead of using for loop, use IntStream.rangeClose() - int sumOfSquares = 0; - for (int i = startInclusive; i <= endInclusive; i++) { - sumOfSquares += i * i; - } - return sumOfSquares; + return IntStream.rangeClosed(startInclusive, endInclusive) + .map(num -> num * num) + .sum(); } } diff --git a/5-0-functional-programming/5-1-1-crazy-lambdas/src/main/java/com/bobocode/fp/CrazyLambdas.java b/5-0-functional-programming/5-1-1-crazy-lambdas/src/main/java/com/bobocode/fp/CrazyLambdas.java index 78feebde2..dcd0a04da 100644 --- a/5-0-functional-programming/5-1-1-crazy-lambdas/src/main/java/com/bobocode/fp/CrazyLambdas.java +++ b/5-0-functional-programming/5-1-1-crazy-lambdas/src/main/java/com/bobocode/fp/CrazyLambdas.java @@ -5,6 +5,7 @@ import java.math.BigDecimal; import java.util.Comparator; import java.util.Map; +import java.util.Random; import java.util.function.*; /** @@ -27,7 +28,8 @@ public class CrazyLambdas { * @return a string supplier */ public static Supplier helloSupplier() { - throw new ExerciseNotCompletedException(); + Supplier supplier = () -> "Hello"; + return supplier; //or can directly return () -> "Hello" } /** @@ -36,7 +38,8 @@ public static Supplier helloSupplier() { * @return a string predicate */ public static Predicate isEmptyPredicate() { - throw new ExerciseNotCompletedException(); + Predicate predicate = (str -> str.isEmpty()); + return predicate; } /** @@ -46,7 +49,8 @@ public static Predicate isEmptyPredicate() { * @return function that repeats Strings */ public static BiFunction stringMultiplier() { - throw new ExerciseNotCompletedException(); + BiFunction function = (str, n) -> str.repeat(n); + return function; } /** @@ -56,7 +60,8 @@ public static BiFunction stringMultiplier() { * @return function that converts adds dollar sign */ public static Function toDollarStringFunction() { - throw new ExerciseNotCompletedException(); + Function bigDecimalStringFunction = (bigDecimal -> "$" + bigDecimal.toString()); + return bigDecimalStringFunction; } /** @@ -68,7 +73,7 @@ public static Function toDollarStringFunction() { * @return a string predicate */ public static Predicate lengthInRangePredicate(int min, int max) { - throw new ExerciseNotCompletedException(); + return (s -> s.length() >= min && s.length() < max); } /** @@ -77,7 +82,7 @@ public static Predicate lengthInRangePredicate(int min, int max) { * @return int supplier */ public static IntSupplier randomIntSupplier() { - throw new ExerciseNotCompletedException(); + return () -> new Random().nextInt(); } @@ -87,7 +92,7 @@ public static IntSupplier randomIntSupplier() { * @return int operation */ public static IntUnaryOperator boundedRandomIntSupplier() { - throw new ExerciseNotCompletedException(); + return (bound) -> new Random(bound).nextInt(); } /** @@ -96,7 +101,7 @@ public static IntUnaryOperator boundedRandomIntSupplier() { * @return square operation */ public static IntUnaryOperator intSquareOperation() { - throw new ExerciseNotCompletedException(); + return (num) -> num * num; } /** @@ -105,7 +110,7 @@ public static IntUnaryOperator intSquareOperation() { * @return binary sum operation */ public static LongBinaryOperator longSumOperation() { - throw new ExerciseNotCompletedException(); + return (num1, num2) -> num1 + num2; } /** @@ -114,7 +119,7 @@ public static LongBinaryOperator longSumOperation() { * @return string to int converter */ public static ToIntFunction stringToIntConverter() { - throw new ExerciseNotCompletedException(); + return (str) -> Integer.parseInt(str); } /** @@ -125,7 +130,8 @@ public static ToIntFunction stringToIntConverter() { * @return a function supplier */ public static Supplier nMultiplyFunctionSupplier(int n) { - throw new ExerciseNotCompletedException(); + IntUnaryOperator operator = (x) -> n * x; + return () -> operator; } /** @@ -134,7 +140,7 @@ public static Supplier nMultiplyFunctionSupplier(int n) { * @return function that composes functions with trim() function */ public static UnaryOperator> composeWithTrimFunction() { - throw new ExerciseNotCompletedException(); + return fun -> fun.compose(s -> s.trim()); } /** @@ -145,7 +151,11 @@ public static UnaryOperator> composeWithTrimFunction() * @return a thread supplier */ public static Supplier runningThreadSupplier(Runnable runnable) { - throw new ExerciseNotCompletedException(); + return () -> { + Thread thread = new Thread(runnable); + thread.run(); + return thread; + }; } /** @@ -154,7 +164,7 @@ public static Supplier runningThreadSupplier(Runnable runnable) { * @return a runnable consumer */ public static Consumer newThreadRunnableConsumer() { - throw new ExerciseNotCompletedException(); + return (runnable) -> runnable.run(); } /** @@ -164,7 +174,7 @@ public static Consumer newThreadRunnableConsumer() { * @return a function that transforms runnable into a thread supplier */ public static Function> runnableToThreadSupplierFunction() { - throw new ExerciseNotCompletedException(); + return (runnable -> runningThreadSupplier(runnable)); } /** @@ -177,7 +187,8 @@ public static Function> runnableToThreadSupplierFunct * @return a binary function that receiver predicate and function and compose them to create a new function */ public static BiFunction functionToConditionalFunction() { - throw new ExerciseNotCompletedException(); + return (fun, predicate) -> + x -> predicate.test(x) ? fun.applyAsInt(x) : x; } /** @@ -188,7 +199,10 @@ public static BiFunction funct * @return a high-order function that fetches a function from a function map by a given name or returns identity() */ public static BiFunction, String, IntUnaryOperator> functionLoader() { - throw new ExerciseNotCompletedException(); + BiFunction, String, IntUnaryOperator> function = + (map, str) -> + map.containsKey(str) ? map.get(str) : IntUnaryOperator.identity(); + return function; } /** @@ -206,7 +220,11 @@ public static BiFunction, String, IntUnaryOperator * @return a comparator instance */ public static > Comparator comparing(Function mapper) { - throw new ExerciseNotCompletedException(); + return (x1, x2) -> { + U u1 = mapper.apply(x1); + U u2 = mapper.apply(x2); + return u1.compareTo(u2); + }; } /** @@ -226,7 +244,7 @@ public static > Comparator comparing(Funct */ public static > Comparator thenComparing( Comparator comparator, Function mapper) { - throw new ExerciseNotCompletedException(); + return (x1, x2) -> comparator.compare(x1, x2) != 0 ? comparator.compare(x1, x2) : comparing(mapper).compare(x1, x2); } /** @@ -235,7 +253,7 @@ public static > Comparator thenComparing( * @return a supplier instance */ public static Supplier>> trickyWellDoneSupplier() { - throw new ExerciseNotCompletedException(); + return () -> () -> () -> "WELL DONE!"; } } diff --git a/5-0-functional-programming/5-2-1-crazy-streams/src/main/java/com/bobocode/fp/CrazyStreams.java b/5-0-functional-programming/5-2-1-crazy-streams/src/main/java/com/bobocode/fp/CrazyStreams.java index 40ffc170f..0991d4e13 100644 --- a/5-0-functional-programming/5-2-1-crazy-streams/src/main/java/com/bobocode/fp/CrazyStreams.java +++ b/5-0-functional-programming/5-2-1-crazy-streams/src/main/java/com/bobocode/fp/CrazyStreams.java @@ -1,12 +1,18 @@ package com.bobocode.fp; +import com.bobocode.fp.exception.EntityNotFoundException; import com.bobocode.model.Account; +import com.bobocode.model.Sex; import com.bobocode.util.ExerciseNotCompletedException; import lombok.AllArgsConstructor; +import org.checkerframework.checker.units.qual.A; +import org.checkerframework.checker.units.qual.C; import java.math.BigDecimal; import java.time.Month; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * {@link CrazyStreams} is an exercise class. Each method represent some operation with a collection of accounts that @@ -24,13 +30,18 @@ public class CrazyStreams { private Collection accounts; + public CrazyStreams(List accounts) { + this.accounts = accounts; + } + /** * Returns {@link Optional} that contains an {@link Account} with the max value of balance * * @return account with max balance wrapped with optional */ public Optional findRichestPerson() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .max(Comparator.comparing(Account::getBalance)); } /** @@ -40,7 +51,9 @@ public Optional findRichestPerson() { * @return a list of accounts */ public List findAccountsByBirthdayMonth(Month birthdayMonth) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .filter(account -> account.getBirthday().getMonth().equals(birthdayMonth)) + .collect(Collectors.toList()); } /** @@ -50,7 +63,8 @@ public List findAccountsByBirthdayMonth(Month birthdayMonth) { * @return a map where key is true or false, and value is list of male, and female accounts */ public Map> partitionMaleAccounts() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.partitioningBy(account -> account.getSex() == Sex.MALE)); } /** @@ -60,7 +74,8 @@ public Map> partitionMaleAccounts() { * @return a map where key is an email domain and value is a list of all account with such email */ public Map> groupAccountsByEmailDomain() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.groupingBy(account -> account.getEmail().split("@")[1])); } /** @@ -69,7 +84,9 @@ public Map> groupAccountsByEmailDomain() { * @return total number of letters of first and last names of all accounts */ public int getNumOfLettersInFirstAndLastNames() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .mapToInt(account -> account.getFirstName().length() + account.getLastName().length()) + .sum(); } /** @@ -78,7 +95,10 @@ public int getNumOfLettersInFirstAndLastNames() { * @return total balance of all accounts */ public BigDecimal calculateTotalBalance() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .map(Account::getBalance) + .reduce(BigDecimal.ZERO, BigDecimal::add); //.reduce(BigDecimal.ZERO, BigDecimal::add) + } /** @@ -87,7 +107,10 @@ public BigDecimal calculateTotalBalance() { * @return list of accounts sorted by first and last names */ public List sortByFirstAndLastNames() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .sorted(Comparator.comparing(Account::getFirstName) + .thenComparing(Account::getLastName)) + .collect(Collectors.toList()); } /** @@ -97,7 +120,8 @@ public List sortByFirstAndLastNames() { * @return true if there is an account that has an email with provided domain */ public boolean containsAccountWithEmailDomain(String emailDomain) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .anyMatch(account -> account.getEmail().contains(emailDomain)); } /** @@ -108,7 +132,11 @@ public boolean containsAccountWithEmailDomain(String emailDomain) { * @return account balance */ public BigDecimal getBalanceByEmail(String email) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .filter(account -> account.getEmail().equals(email)) + .findAny() + .map(Account::getBalance) + .orElseThrow(() -> new EntityNotFoundException("Cannot find Account by email=" + email)); } /** @@ -117,7 +145,8 @@ public BigDecimal getBalanceByEmail(String email) { * @return map of accounts by its ids */ public Map collectAccountsById() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.toMap(Account::getId, account -> account)); } /** @@ -128,7 +157,9 @@ public Map collectAccountsById() { * @return map of account by its ids the were created in a particular year */ public Map collectBalancesByEmailForAccountsCreatedOn(int year) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .filter(account -> account.getCreationDate().getYear() == year) + .collect(Collectors.toMap(Account::getEmail, Account::getBalance)); } /** @@ -138,7 +169,13 @@ public Map collectBalancesByEmailForAccountsCreatedOn(int ye * @return a map where key is a last name and value is a set of first names */ public Map> groupFirstNamesByLastNames() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.groupingBy( + Account::getLastName, + Collectors.mapping(Account::getFirstName, Collectors.toSet() + ) + )); + } /** @@ -148,7 +185,10 @@ public Map> groupFirstNamesByLastNames() { * @return a map where a key is a birthday month and value is comma-separated first names */ public Map groupCommaSeparatedFirstNamesByBirthdayMonth() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.groupingBy(account -> account.getBirthday().getMonth(), + Collectors.mapping(Account::getFirstName, Collectors.joining(", ") + ))); } /** @@ -158,7 +198,9 @@ public Map groupCommaSeparatedFirstNamesByBirthdayMonth() { * @return a map where key is a creation month and value is total balance of all accounts created in that month */ public Map groupTotalBalanceByCreationMonth() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .collect(Collectors.groupingBy(account -> account.getCreationDate().getMonth(), + Collectors.reducing(BigDecimal.ZERO, Account::getBalance, BigDecimal::add))); } /** @@ -168,7 +210,13 @@ public Map groupTotalBalanceByCreationMonth() { * @return a map where key is a letter and value is its count in all first names */ public Map getCharacterFrequencyInFirstNames() { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .filter(Objects::nonNull) + .map(Account::getFirstName) + .flatMapToInt(String::chars) + .mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(c -> c, + Collectors.counting())); } /** @@ -179,7 +227,15 @@ public Map getCharacterFrequencyInFirstNames() { * @return a map where key is a letter and value is its count ignoring case in all first and last names */ public Map getCharacterFrequencyIgnoreCaseInFirstAndLastNames(int nameLengthBound) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .flatMap(account -> Stream.of(account.getFirstName(), account.getLastName())) + .filter(Objects::nonNull) + .map(String::toLowerCase) + .filter(name -> name.length() >= nameLengthBound) + .flatMapToInt(String::chars) + .mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(c -> c, + Collectors.counting())); } } diff --git a/5-0-functional-programming/5-3-1-crazy-optionals/src/main/java/com/bobocode/fp/CrazyOptionals.java b/5-0-functional-programming/5-3-1-crazy-optionals/src/main/java/com/bobocode/fp/CrazyOptionals.java index 1ab1faa67..772a91f04 100644 --- a/5-0-functional-programming/5-3-1-crazy-optionals/src/main/java/com/bobocode/fp/CrazyOptionals.java +++ b/5-0-functional-programming/5-3-1-crazy-optionals/src/main/java/com/bobocode/fp/CrazyOptionals.java @@ -12,9 +12,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.math.BigDecimal; -import java.util.List; -import java.util.Optional; -import java.util.OptionalDouble; +import java.util.*; /** * {@link CrazyOptionals} is an exercise class. Each method represents some operation with a {@link Account} and @@ -37,7 +35,7 @@ public class CrazyOptionals { * @return optional object that holds text */ public static Optional optionalOfString(@Nullable String text) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(text); } /** @@ -47,7 +45,8 @@ public static Optional optionalOfString(@Nullable String text) { * @param amount money to deposit */ public static void deposit(AccountProvider accountProvider, BigDecimal amount) { - throw new ExerciseNotCompletedException(); + accountProvider.getAccount() + .ifPresent(acc -> acc.setBalance(acc.getBalance().add(amount))); } /** @@ -57,7 +56,7 @@ public static void deposit(AccountProvider accountProvider, BigDecimal amount) { * @return optional object that holds account */ public static Optional optionalOfAccount(@Nonnull Account account) { - throw new ExerciseNotCompletedException(); + return Optional.of(account); } /** @@ -69,7 +68,8 @@ public static Optional optionalOfAccount(@Nonnull Account account) { * @return account from provider or defaultAccount */ public static Account getAccount(AccountProvider accountProvider, Account defaultAccount) { - throw new ExerciseNotCompletedException(); + return accountProvider.getAccount() + .orElse(defaultAccount); } /** @@ -80,7 +80,7 @@ public static Account getAccount(AccountProvider accountProvider, Account defaul * @param accountService */ public static void processAccount(AccountProvider accountProvider, AccountService accountService) { - throw new ExerciseNotCompletedException(); + accountProvider.getAccount().ifPresentOrElse(accountService::processAccount, accountService::processWithNoAccount); } /** @@ -91,7 +91,8 @@ public static void processAccount(AccountProvider accountProvider, AccountServic * @return provided or generated account */ public static Account getOrGenerateAccount(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return accountProvider.getAccount() + .orElseGet(Accounts::generateAccount); } /** @@ -101,7 +102,9 @@ public static Account getOrGenerateAccount(AccountProvider accountProvider) { * @return optional balance */ public static Optional retrieveBalance(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) // Optional + .flatMap(AccountProvider::getAccount) // Optional + .map(Account::getBalance); // Optional } /** @@ -112,7 +115,8 @@ public static Optional retrieveBalance(AccountProvider accountProvid * @return provided account */ public static Account getAccount(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return accountProvider.getAccount() + .orElseThrow(() -> new AccountNotFoundException("No Account provided!")); } /** @@ -122,7 +126,9 @@ public static Account getAccount(AccountProvider accountProvider) { * @return optional credit balance */ public static Optional retrieveCreditBalance(CreditAccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) // Optional + .flatMap(CreditAccountProvider::getAccount) // Optional + .flatMap(CreditAccount::getCreditBalance); // Optional } @@ -134,7 +140,8 @@ public static Optional retrieveCreditBalance(CreditAccountProvider a * @return optional gmail account */ public static Optional retrieveAccountGmail(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return accountProvider.getAccount() + .filter(account -> account.getEmail() != null && account.getEmail().endsWith("gmail.com")); } /** @@ -147,7 +154,9 @@ public static Optional retrieveAccountGmail(AccountProvider accountProv * @return account got from either accountProvider or fallbackProvider */ public static Account getAccountWithFallback(AccountProvider accountProvider, AccountProvider fallbackProvider) { - throw new ExerciseNotCompletedException(); + return accountProvider.getAccount() + .or(fallbackProvider::getAccount) + .orElseThrow(NoSuchElementException::new); } /** @@ -158,7 +167,9 @@ public static Account getAccountWithFallback(AccountProvider accountProvider, Ac * @return account with the highest balance */ public static Account getAccountWithMaxBalance(List accounts) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .max(Comparator.comparing(Account::getBalance)) // numeric comparison + .orElseThrow(NoSuchElementException::new); } /** @@ -168,7 +179,10 @@ public static Account getAccountWithMaxBalance(List accounts) { * @return the lowest balance values */ public static OptionalDouble findMinBalanceValue(List accounts) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .map(Account::getBalance) // BigDecimal ↘︎ + .mapToDouble(BigDecimal::doubleValue) // DoubleStream + .min(); } /** @@ -178,7 +192,7 @@ public static OptionalDouble findMinBalanceValue(List accounts) { * @param accountService */ public static void processAccountWithMaxBalance(List accounts, AccountService accountService) { - throw new ExerciseNotCompletedException(); + accountService.processAccount(getAccountWithMaxBalance(accounts)); } /** @@ -188,7 +202,10 @@ public static void processAccountWithMaxBalance(List accounts, AccountS * @return total credit balance */ public static double calculateTotalCreditBalance(List accounts) { - throw new ExerciseNotCompletedException(); + return accounts.stream() + .map(CreditAccount::getCreditBalance) + .flatMap(Optional::stream) // Stream + .mapToDouble(BigDecimal::doubleValue) // convert to primitive double + .sum(); // sum the doubles } -} - +} \ No newline at end of file diff --git a/5-0-functional-programming/5-4-1-fun-prime-numbers/src/main/java/com/bobocode/fp/PrimeNumbers.java b/5-0-functional-programming/5-4-1-fun-prime-numbers/src/main/java/com/bobocode/fp/PrimeNumbers.java index e4a99188d..8bcd64eb7 100644 --- a/5-0-functional-programming/5-4-1-fun-prime-numbers/src/main/java/com/bobocode/fp/PrimeNumbers.java +++ b/5-0-functional-programming/5-4-1-fun-prime-numbers/src/main/java/com/bobocode/fp/PrimeNumbers.java @@ -2,9 +2,11 @@ import com.bobocode.util.ExerciseNotCompletedException; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.IntConsumer; +import java.util.stream.Collectors; import java.util.stream.IntStream; /** @@ -30,7 +32,19 @@ private PrimeNumbers() { * @return an infinite int stream of prime numbers */ public static IntStream stream() { - throw new ExerciseNotCompletedException(); // todo: create an infinite stream of ints, then filter prime numbs + return IntStream.iterate(2, n -> n + 1) // 2, 3, 4, 5 … + .filter(PrimeNumbers::isPrime); // keep only primes + } + + /* helper – visible only inside this class */ + private static boolean isPrime(int n) { + if (n < 2) return false; + if (n == 2) return true; + if (n % 2 == 0) return false; + int sqrt = (int) Math.sqrt(n); + return IntStream.rangeClosed(3, sqrt) + .filter(i -> (i & 1) == 1) // test odd divisors only + .noneMatch(i -> n % i == 0); // no divisor ⇒ prime } /** @@ -40,7 +54,7 @@ public static IntStream stream() { * @return an int stream of prime numbers with a specified size */ public static IntStream stream(int size) { - throw new ExerciseNotCompletedException(); // todo: use the prev to generate a stream method but limit its size + return stream().limit(size); } /** @@ -51,7 +65,7 @@ public static IntStream stream(int size) { * @return the sum of n prime numbers */ public static int sum(int n) { - throw new ExerciseNotCompletedException(); // todo: use prev method and calculate the sum + return stream().limit(n).sum(); } @@ -61,7 +75,10 @@ public static int sum(int n) { * @return a list of collected prime numbers */ public static List list(int n) { - throw new ExerciseNotCompletedException(); // todo: collect prime numbers into the list + return stream() + .limit(n) + .boxed() + .toList(); } /** @@ -71,7 +88,10 @@ public static List list(int n) { * @param consumer a logic that should be applied to the found prime number */ public static void processByIndex(int idx, IntConsumer consumer) { - throw new ExerciseNotCompletedException(); // todo: find an element in the stream by index and process it + stream() + .skip(idx) + .findFirst() + .ifPresent(consumer); } /** @@ -85,6 +105,9 @@ public static void processByIndex(int idx, IntConsumer consumer) { * @return a map with prime number grouped by the amount of digits */ public static Map> groupByAmountOfDigits(int n) { - throw new ExerciseNotCompletedException(); // todo: group n prime numbers by the amount of digits + return stream() + .limit(n) + .boxed() + .collect(Collectors.groupingBy(i -> String.valueOf(i).length())); } -} +} \ No newline at end of file diff --git a/java-fundamentals-util/src/main/java/com/bobocode/model/Account.java b/java-fundamentals-util/src/main/java/com/bobocode/model/Account.java index c41a89872..325bc0bc5 100644 --- a/java-fundamentals-util/src/main/java/com/bobocode/model/Account.java +++ b/java-fundamentals-util/src/main/java/com/bobocode/model/Account.java @@ -20,5 +20,41 @@ public class Account { private Sex sex; private LocalDate creationDate; private BigDecimal balance = BigDecimal.ZERO; + + public Long getId() { + return id; + } + + public String getEmail() { + return email; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public LocalDate getBirthday() { + return birthday; + } + + public Sex getSex() { + return sex; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } } From 7bd908003fc13110bbfb16625d8a54956cbb65ce Mon Sep 17 00:00:00 2001 From: Milena Hakobyan Date: Tue, 27 May 2025 13:35:02 +0400 Subject: [PATCH 2/2] removing files that shouldnt be tracked --- 0-0-intro/README.md | 29 - 0-0-intro/pom.xml | 22 - .../bobocode/intro/ExerciseIntroduction.java | 45 -- .../intro/ExerciseIntroductionTest.java | 51 -- .../1-5-0-hello-annotations/README.MD | 20 - .../1-5-0-hello-annotations/pom.xml | 14 - .../basics/HelloAnnotationsExercise.java | 17 - .../main/java/com/bobocode/basics/Level.java | 8 - .../basics/HelloAnnotationsExerciseTest.java | 101 --- .../2-2-1-node/README.MD | 22 - .../2-2-1-node/pom.xml | 15 - .../src/main/java/com/bobobode/cs/Node.java | 13 - .../src/main/java/com/bobobode/cs/Nodes.java | 90 --- .../test/java/com/bobocode/cs/NodesTest.java | 173 ----- .../2-2-2-stack/README.md | 27 - .../2-2-2-stack/pom.xml | 15 - .../java/com/bobocode/cs/LinkedStack.java | 73 -- .../src/main/java/com/bobocode/cs/Stack.java | 21 - .../cs/exception/EmptyStackException.java | 5 - .../java/com/bobocode/cs/LinkedStackTest.java | 414 ----------- .../2-2-3-linked-queue/README.MD | 17 - .../2-2-3-linked-queue/pom.xml | 15 - .../java/com/bobocode/cs/LinkedQueue.java | 54 -- .../src/main/java/com/bobocode/cs/Queue.java | 35 - .../java/com/bobocode/cs/LinkedQueueTest.java | 377 ---------- .../2-2-4-linked-list/README.MD | 22 - .../2-2-4-linked-list/pom.xml | 23 - .../main/java/com/bobocode/cs/LinkedList.java | 148 ---- .../java/com/bobocode/cs/LinkedListTest.java | 614 ---------------- .../2-2-5-array-list/README.MD | 27 - .../2-2-5-array-list/pom.xml | 22 - .../main/java/com/bobocode/cs/ArrayList.java | 159 ---- .../java/com/bobocode/cs/ArrayListTest.java | 406 ----------- .../2-2-6-binary-search-tree/README.md | 24 - .../2-2-6-binary-search-tree/pom.xml | 15 - .../com/bobocode/cs/BinarySearchTree.java | 32 - .../cs/RecursiveBinarySearchTree.java | 49 -- .../cs/RecursiveBinarySearchTreeTest.java | 447 ------------ .../2-2-9-hash-table/README.md | 16 - .../2-2-9-hash-table/pom.xml | 15 - .../main/java/com/bobocode/cs/HashTable.java | 172 ----- .../src/main/java/com/bobocode/cs/Map.java | 69 -- .../java/com/bobocode/cs/HashTableTest.java | 677 ------------------ 2-0-data-structures-and-algorithms/README.md | 2 - .../pom.xml | 15 - .../src/main/java/com/bobocode/cs/List.java | 26 - 2-0-data-structures-and-algorithms/pom.xml | 35 - 3-0-java-core/3-6-1-file-reader/README.MD | 17 - 3-0-java-core/3-6-1-file-reader/pom.xml | 15 - .../java/com/bobocode/se/FileReaders.java | 19 - .../java/com/bobocode/se/FileReadersTest.java | 34 - .../src/test/resources/empty.txt | 0 .../src/test/resources/lines.txt | 5 - .../src/test/resources/simple.txt | 2 - 3-0-java-core/3-6-2-file-stats/README.MD | 20 - 3-0-java-core/3-6-2-file-stats/pom.xml | 15 - .../main/java/com/bobocode/se/FileStats.java | 48 -- .../com/bobocode/se/FileStatsException.java | 11 - .../java/com/bobocode/se/FileStatsTest.java | 69 -- .../src/test/resources/scosb.txt | 3 - .../src/test/resources/sotl.txt | 411 ----------- 3-0-java-core/3-6-3-crazy-regex/README.MD | 66 -- 3-0-java-core/3-6-3-crazy-regex/pom.xml | 15 - .../main/java/com/bobocode/se/CrazyRegex.java | 255 ------- .../java/com/bobocode/se/CrazyRegexTest.java | 246 ------- .../src/test/resources/nasa.json | 23 - .../src/test/resources/note.txt | 9 - .../4-3-1-flight-search/README.MD | 26 - .../4-3-1-flight-search/pom.xml | 15 - .../java/com/bobocode/oop/data/FlightDao.java | 37 - .../oop/factory/FlightServiceFactory.java | 21 - .../bobocode/oop/service/FlightService.java | 34 - .../com/bobocode/oop/FlightServiceTest.java | 65 -- 4-0-object-oriented-programming/README.md | 2 - 4-0-object-oriented-programming/pom.xml | 28 - .../6-1-1-stack/README.md | 26 - .../6-1-1-stack/pom.xml | 15 - .../java/com/bobocode/tdd/LinkedStack.java | 25 - .../src/main/java/com/bobocode/tdd/Stack.java | 35 - .../test/java/com/bobocode/tdd/StackTest.java | 4 - .../6-1-2-linked-list/README.MD | 32 - .../6-1-2-linked-list/pom.xml | 15 - .../java/com/bobocode/tdd/LinkedList.java | 143 ---- .../src/main/java/com/bobocode/tdd/List.java | 27 - .../java/com/bobocode/tdd/LinkedListTest.java | 4 - .../6-1-3-binary-search-tree/README.md | 27 - .../6-1-3-binary-search-tree/pom.xml | 15 - .../com/bobocode/tdd/BinarySearchTree.java | 32 - .../tdd/RecursiveBinarySearchTree.java | 37 - .../bobocode/tdd/BinarySearchTreeTest.java | 5 - 6-0-test-driven-development/README.md | 9 - 6-0-test-driven-development/pom.xml | 30 - 92 files changed, 6680 deletions(-) delete mode 100644 0-0-intro/README.md delete mode 100644 0-0-intro/pom.xml delete mode 100644 0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java delete mode 100644 0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java delete mode 100644 1-0-java-basics/1-5-0-hello-annotations/README.MD delete mode 100644 1-0-java-basics/1-5-0-hello-annotations/pom.xml delete mode 100644 1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/HelloAnnotationsExercise.java delete mode 100644 1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Level.java delete mode 100644 1-0-java-basics/1-5-0-hello-annotations/src/test/java/com/bobocode/basics/HelloAnnotationsExerciseTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-1-node/README.MD delete mode 100644 2-0-data-structures-and-algorithms/2-2-1-node/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Node.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Nodes.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-1-node/src/test/java/com/bobocode/cs/NodesTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/README.md delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/LinkedStack.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/Stack.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/exception/EmptyStackException.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-2-stack/src/test/java/com/bobocode/cs/LinkedStackTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-3-linked-queue/README.MD delete mode 100644 2-0-data-structures-and-algorithms/2-2-3-linked-queue/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/LinkedQueue.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/Queue.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/test/java/com/bobocode/cs/LinkedQueueTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-4-linked-list/README.MD delete mode 100644 2-0-data-structures-and-algorithms/2-2-4-linked-list/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-4-linked-list/src/main/java/com/bobocode/cs/LinkedList.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-4-linked-list/src/test/java/com/bobocode/cs/LinkedListTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-5-array-list/README.MD delete mode 100644 2-0-data-structures-and-algorithms/2-2-5-array-list/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-5-array-list/src/main/java/com/bobocode/cs/ArrayList.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-5-array-list/src/test/java/com/bobocode/cs/ArrayListTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/README.md delete mode 100644 2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/BinarySearchTree.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/RecursiveBinarySearchTree.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/test/java/com/bobocode/cs/RecursiveBinarySearchTreeTest.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-9-hash-table/README.md delete mode 100644 2-0-data-structures-and-algorithms/2-2-9-hash-table/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/HashTable.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/Map.java delete mode 100644 2-0-data-structures-and-algorithms/2-2-9-hash-table/src/test/java/com/bobocode/cs/HashTableTest.java delete mode 100644 2-0-data-structures-and-algorithms/README.md delete mode 100644 2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/pom.xml delete mode 100644 2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/src/main/java/com/bobocode/cs/List.java delete mode 100644 2-0-data-structures-and-algorithms/pom.xml delete mode 100644 3-0-java-core/3-6-1-file-reader/README.MD delete mode 100644 3-0-java-core/3-6-1-file-reader/pom.xml delete mode 100644 3-0-java-core/3-6-1-file-reader/src/main/java/com/bobocode/se/FileReaders.java delete mode 100644 3-0-java-core/3-6-1-file-reader/src/test/java/com/bobocode/se/FileReadersTest.java delete mode 100644 3-0-java-core/3-6-1-file-reader/src/test/resources/empty.txt delete mode 100644 3-0-java-core/3-6-1-file-reader/src/test/resources/lines.txt delete mode 100644 3-0-java-core/3-6-1-file-reader/src/test/resources/simple.txt delete mode 100644 3-0-java-core/3-6-2-file-stats/README.MD delete mode 100644 3-0-java-core/3-6-2-file-stats/pom.xml delete mode 100644 3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStats.java delete mode 100644 3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStatsException.java delete mode 100644 3-0-java-core/3-6-2-file-stats/src/test/java/com/bobocode/se/FileStatsTest.java delete mode 100644 3-0-java-core/3-6-2-file-stats/src/test/resources/scosb.txt delete mode 100644 3-0-java-core/3-6-2-file-stats/src/test/resources/sotl.txt delete mode 100644 3-0-java-core/3-6-3-crazy-regex/README.MD delete mode 100644 3-0-java-core/3-6-3-crazy-regex/pom.xml delete mode 100644 3-0-java-core/3-6-3-crazy-regex/src/main/java/com/bobocode/se/CrazyRegex.java delete mode 100644 3-0-java-core/3-6-3-crazy-regex/src/test/java/com/bobocode/se/CrazyRegexTest.java delete mode 100644 3-0-java-core/3-6-3-crazy-regex/src/test/resources/nasa.json delete mode 100644 3-0-java-core/3-6-3-crazy-regex/src/test/resources/note.txt delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/README.MD delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/pom.xml delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/FlightDao.java delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/factory/FlightServiceFactory.java delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/service/FlightService.java delete mode 100644 4-0-object-oriented-programming/4-3-1-flight-search/src/test/java/com/bobocode/oop/FlightServiceTest.java delete mode 100644 4-0-object-oriented-programming/README.md delete mode 100644 4-0-object-oriented-programming/pom.xml delete mode 100644 6-0-test-driven-development/6-1-1-stack/README.md delete mode 100644 6-0-test-driven-development/6-1-1-stack/pom.xml delete mode 100644 6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/LinkedStack.java delete mode 100644 6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/Stack.java delete mode 100644 6-0-test-driven-development/6-1-1-stack/src/test/java/com/bobocode/tdd/StackTest.java delete mode 100644 6-0-test-driven-development/6-1-2-linked-list/README.MD delete mode 100644 6-0-test-driven-development/6-1-2-linked-list/pom.xml delete mode 100644 6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/LinkedList.java delete mode 100644 6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/List.java delete mode 100644 6-0-test-driven-development/6-1-2-linked-list/src/test/java/com/bobocode/tdd/LinkedListTest.java delete mode 100644 6-0-test-driven-development/6-1-3-binary-search-tree/README.md delete mode 100644 6-0-test-driven-development/6-1-3-binary-search-tree/pom.xml delete mode 100644 6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/BinarySearchTree.java delete mode 100644 6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/RecursiveBinarySearchTree.java delete mode 100644 6-0-test-driven-development/6-1-3-binary-search-tree/src/test/java/com/bobocode/tdd/BinarySearchTreeTest.java delete mode 100644 6-0-test-driven-development/README.md delete mode 100644 6-0-test-driven-development/pom.xml diff --git a/0-0-intro/README.md b/0-0-intro/README.md deleted file mode 100644 index 488324028..000000000 --- a/0-0-intro/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Introduction - -Learn how to use this course to build strong skill needed for enterprise Java development - -## The only way to learn effectively is to **learn by doing!** 💪 - -Therefore, this whole repository consists of **various exercises grouped by topics**. By doing exercises you will **build strong skills and neven get stuck.** Introduction itself is an exercise, so you can understand the idea on the simplest example. - -Each exercise has three major parts: -* **a task** – some logic that you implement in order build a certain skill 👨🏻‍💻 -* **a test** – a corresponding test that verifies if you implement the task correctly ▶️ -* **a completed solution** - a branch `completed` that holds implemented task ✅ - -Go ahead and do this exercise by implementing a method in `Introduction` class. 💪 -_(we know it's silly, but we wanted to give you a simple example 😀)_ - -## You should have installed on your local machine ❗️ -* [JDK 11+](https://jdk.java.net/15/) -* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) - -## How to start ❓ -* [clone](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) this [repository](https://github.com/bobocode-projects/java-fundamentals-exercises) to your computer -* **open** the project via IDE - -## Have questions? 🧐 -* take a look at **README** of the exercise -* switch to branch `completed` and **see the correct implementation** of the exercise -* [join the discussion](https://github.com/bobocode-projects/java-fundamentals-exercises/discussions) on the GitHub -* contact us via info@bobocode.com diff --git a/0-0-intro/pom.xml b/0-0-intro/pom.xml deleted file mode 100644 index b62fec52e..000000000 --- a/0-0-intro/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - 4.0.0 - - - com.bobocode - java-fundamentals-exercises - 1.0-SNAPSHOT - - 0-0-intro - - - - com.bobocode - java-fundamentals-util - 1.0-SNAPSHOT - - - - \ No newline at end of file diff --git a/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java b/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java deleted file mode 100644 index 35d925636..000000000 --- a/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.bobocode.intro; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * Welcome! This is an introduction exercise that will show you a simple example of Bobocode exercises. - *

- * JavaDoc is a way of communication with other devs. We use Java Docs in every exercise to define the task. - * So PLEASE MAKE SURE you read the Java Docs carefully. - *

- * Every exercise is covered with tests, see {@link ExerciseIntroductionTest}. - *

- * In this repo you'll find dozens of exercises covering various fundamental topics. - * They all have the same structure helping you to focus on practice and build strong skills! - * - * @author Taras Boychuk - */ -public class ExerciseIntroduction { - /** - * This method returns a very important message. If understood well, it can save you years of inefficient learning, - * and unlock your potential! - * - * @return "The key to efficient learning is practice!" - */ - public String getWelcomeMessage() { - // todo: implement a method and return a message according to javadoc - throw new ExerciseNotCompletedException(); - } - - /** - * Method encodeMessage accepts one {@link String} parameter and returns encoded {@link String}. - *

- * PLEASE NOTE THAT YOU WILL GET STUCK ON THIS METHOD INTENTIONALLY! ;) - *

- * Every exercise has a completed solution that is stored in the branch "completed". So in case you got stuck - * and don't know what to do, go check out completed solution. - * - * @param message input message - * @return encoded message - */ - public String encodeMessage(String message) { - // todo: switch to branch "completed" in order to see how it should be implemented - throw new ExerciseNotCompletedException(); - } -} diff --git a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java b/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java deleted file mode 100644 index 093909fe9..000000000 --- a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.bobocode.intro; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.*; - -import java.util.Arrays; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * This is a {@link ExerciseIntroductionTest} that is meant to verify if you properly implement {@link ExerciseIntroduction}. - * It is a simple example that shows how each exercise is organized: todo section + tests. - *

- * A typical Java test uses JUnit framework to run the test, and may also use some other frameworks for assertions. - * In our exercises we use JUnit 5 + AssertJ - *

- * PLEASE NOTE: - * - annotation @{@link Order} is used to help you to understand which method should be implemented first. - * - annotation @{@link DisplayName} is used to provide you more detailed instructions. - * - * @author Taras Boychuk - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class ExerciseIntroductionTest { - private ExerciseIntroduction exerciseIntroduction = new ExerciseIntroduction(); - private String EXPECTED_MESSAGE = "The key to efficient learning is practice!"; - - @Test - @Order(1) - @DisplayName("getWelcomeMessage method returns correct phrase") - void getWelcomeMessage() { - String message = exerciseIntroduction.getWelcomeMessage(); - - assertThat(message).isEqualTo(EXPECTED_MESSAGE); - } - - @Test - @Order(2) - @DisplayName("encodeMessage returns correct encoded message") - @SneakyThrows - void encodeMessageReturnsCorrectPhrase() { - var encodeMessageMethod = Arrays.stream(ExerciseIntroduction.class.getDeclaredMethods()) - .filter(method -> method.getName().equals("encodeMessage")) - .findAny() - .orElseThrow(); - - var encodedMessage = encodeMessageMethod.invoke(new ExerciseIntroduction(), EXPECTED_MESSAGE); - - assertThat(encodedMessage).isEqualTo("VGhlIGtleSB0byBlZmZpY2llbnQgbGVhcm5pbmcgaXMgcHJhY3RpY2Uh"); - } -} diff --git a/1-0-java-basics/1-5-0-hello-annotations/README.MD b/1-0-java-basics/1-5-0-hello-annotations/README.MD deleted file mode 100644 index 70290ad7f..000000000 --- a/1-0-java-basics/1-5-0-hello-annotations/README.MD +++ /dev/null @@ -1,20 +0,0 @@ -# Hello Annotations -Learn annotations basics to better understand how the frameworks use them 💪 - -### Objectives - -* **create a custom annotation** ✅ -* specify **where it can be used** ([`@Target`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Target.html)) ✅ -* specify **where its information can be accessed** ([`@Retention`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Retention.html)) ✅ -* add **annotation members** (methods that act like fields) ✅ -* set **default value** for a member ✅ -* **use custom annotation** on a class ✅ - - -### Exercise overview 🇺🇦 -[![Watch the video](https://img.youtube.com/vi/KF1H2EOCdD4/0.jpg)](https://www.youtube.com/watch?v=KF1H2EOCdD4) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) -## -

\ No newline at end of file diff --git a/1-0-java-basics/1-5-0-hello-annotations/pom.xml b/1-0-java-basics/1-5-0-hello-annotations/pom.xml deleted file mode 100644 index 753aac6cf..000000000 --- a/1-0-java-basics/1-5-0-hello-annotations/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - 1-0-java-basics - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 1-5-0-hello-annotations - - \ No newline at end of file diff --git a/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/HelloAnnotationsExercise.java b/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/HelloAnnotationsExercise.java deleted file mode 100644 index 4dc8c4b22..000000000 --- a/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/HelloAnnotationsExercise.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.bobocode.basics; - -/** - * {@link HelloAnnotationsExercise} is an exercise class that is marked with be corresponding @{@link Exercise} - * annotation. The annotation value specifies exercise name "hello-annotation-basic". It does not specify any custom - * complexity level, because this exercise is a basic, which correspond to the default value provided by annotation. - *

- * todo: Create an annotation @{@link Exercise}. - * todo: Set its retention policy so it is visible at runtime - * todo: Set its target so it can only be applied to a class - * todo: Add String value that will store exercise name - * todo: Add complexityLevel with a default {@link Level} basic - * - * @author Taras Boychuk - */ -public class HelloAnnotationsExercise { // todo: mark class with the annotation according to the javadoc -} diff --git a/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Level.java b/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Level.java deleted file mode 100644 index 28a1deb00..000000000 --- a/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Level.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.bobocode.basics; - -/** - * Enum that lists all possible exercise complexity levels. - */ -public enum Level { - BEGINNER, BASIC, ADVANCED, CRAZY -} diff --git a/1-0-java-basics/1-5-0-hello-annotations/src/test/java/com/bobocode/basics/HelloAnnotationsExerciseTest.java b/1-0-java-basics/1-5-0-hello-annotations/src/test/java/com/bobocode/basics/HelloAnnotationsExerciseTest.java deleted file mode 100644 index b0d991543..000000000 --- a/1-0-java-basics/1-5-0-hello-annotations/src/test/java/com/bobocode/basics/HelloAnnotationsExerciseTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.bobocode.basics; - - -import lombok.SneakyThrows; -import org.junit.jupiter.api.*; - -import java.lang.annotation.*; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; - -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class HelloAnnotationsExerciseTest { - - @Test - @Order(1) - @DisplayName("Annotation @Exercise exists") - void exerciseAnnotationExists() { - assertThatCode(this::getExerciseAnnotation).doesNotThrowAnyException(); - } - - @Test - @Order(2) - @DisplayName("@Exercise can be applied to classes and interfaces but not to methods & fields") - @SneakyThrows - void exerciseAnnotationCanBeAppliedForClasses() { - var exerciseAnnotation = getExerciseAnnotation(); - - var target = exerciseAnnotation.getAnnotation(Target.class); - - assertThat(target.value()).hasSize(1); - assertThat(target.value()[0]).isEqualTo(ElementType.TYPE); - } - - @Test - @Order(3) - @DisplayName("@Exercise information is accessible at runtime") - @SneakyThrows - void exerciseAnnotationInfoIsAccessibleAtRuntime() { - var exerciseAnnotation = getExerciseAnnotation(); - - var retention = exerciseAnnotation.getAnnotation(Retention.class); - - assertThat(retention.value()).isEqualTo(RetentionPolicy.RUNTIME); - } - - @Test - @Order(4) - @DisplayName("@Exercise has declared value") - @SneakyThrows - void exerciseAnnotationHasValueDeclared() { - var exerciseAnnotation = getExerciseAnnotation(); - - assertThatCode(() -> exerciseAnnotation.getDeclaredMethod("value")) - .doesNotThrowAnyException(); - } - - @Test - @Order(4) - @DisplayName("@Exercise has complexityLevel declared") - @SneakyThrows - void exerciseAnnotationHasComplexityDeclared() { - var exerciseAnnotation = getExerciseAnnotation(); - - assertThatCode(() -> exerciseAnnotation.getDeclaredMethod("complexityLevel")) - .doesNotThrowAnyException(); - } - - @Test - @Order(5) - @DisplayName("@Exercise complexityLevel is BASIC by default") - @SneakyThrows - void exerciseAnnotationComplexityLevelDefaultValue() { - var exerciseAnnotation = getExerciseAnnotation(); - - var complexityLevel = exerciseAnnotation.getDeclaredMethod("complexityLevel"); - - assertThat(complexityLevel.getDefaultValue()).isEqualTo(Level.BASIC); - } - - @Test - @Order(6) - @DisplayName("HelloAnnotationExercise is marked as @Exercise with name \"hello-annotation-basic\"") - @SneakyThrows - void helloAnnotationExerciseIsAnnotatedWithExercise() { - var exerciseAnnotationClass = getExerciseAnnotation(); - var basicExerciseAnnotation = HelloAnnotationsExercise.class.getAnnotation(exerciseAnnotationClass); - - var valueMethod = exerciseAnnotationClass.getMethod("value"); - var exerciseName = valueMethod.invoke(basicExerciseAnnotation); - - assertThat(exerciseName).isEqualTo("hello-annotation-basic"); - } - - @SneakyThrows - private Class getExerciseAnnotation() { - return Class.forName("com.bobocode.basics.Exercise") - .asSubclass(Annotation.class); - } - -} diff --git a/2-0-data-structures-and-algorithms/2-2-1-node/README.MD b/2-0-data-structures-and-algorithms/2-2-1-node/README.MD deleted file mode 100644 index 036f631c6..000000000 --- a/2-0-data-structures-and-algorithms/2-2-1-node/README.MD +++ /dev/null @@ -1,22 +0,0 @@ -# Node exercise 💪 - -Build strong skill of creating and linking **nodes – building blocks** that are used in order to create **LinkedList**, **LinkedQueue** and other -important data structures 💪 - -### Pre-conditions ❗ -You're supposed to be familiar **Java classes** and **generics** - -### Objectives -* implement a generic class `Node` ✅ -* **link** two node objects ✅ -* create a **list of linked nodes** ✅ -* create a **circle of linked nodes** ✅ - -### Exercise overview 🇺🇦 -[![Watch the video](https://img.youtube.com/vi/Ot5ma8NXcS0/0.jpg)](https://www.youtube.com/watch?v=Ot5ma8NXcS0) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-1-node/pom.xml b/2-0-data-structures-and-algorithms/2-2-1-node/pom.xml deleted file mode 100644 index 6549f9d70..000000000 --- a/2-0-data-structures-and-algorithms/2-2-1-node/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-1-node - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Node.java b/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Node.java deleted file mode 100644 index b01a4acfb..000000000 --- a/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Node.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.bobobode.cs; - -/** - * Class {@link Node} is a very simple data structure that consists of an element itself and the reference to the next - * node. An element can have any value since it's a generic. A reference to the next node allows to link {@link Node} - * objects and build more comprehensive data structures on top of those liked nodes. - * - * @param a generic type T - * @author Taras Boychuk - */ -public class Node { - // todo: -} diff --git a/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Nodes.java b/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Nodes.java deleted file mode 100644 index 5321aa53a..000000000 --- a/2-0-data-structures-and-algorithms/2-2-1-node/src/main/java/com/bobobode/cs/Nodes.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.bobobode.cs; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * A class that consists of static methods only and provides util methods for {@link Node}. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @author Taras Boychuk - */ -public class Nodes { - private Nodes() { - } - - /** - * Creates a new instance of {@link Node} that holds provided element - * - * @param element any element of type T - * @param generic type - * @return a new instance of {@link Node} - */ - public static Node create(T element) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Create a connection between first and second nodes, so object first stores a reference to the second. - * - * @param first any {@link Node} object - * @param second any {@link Node} object - * @param a genetic type - */ - public static void link(Node first, Node second) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates two new {@link Node} objects using provided firstElement and secondElement, and create a connection - * between those two elements so the first node will hold a reference to a second one. - * - * @param firstElement any element of type T - * @param secondElement any element of type T - * @param a genetic type - * @return a reference to a first node created based on firstElement - */ - public static Node pairOf(T firstElement, T secondElement) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates two new {@link Node} objects using provided firstElement and secondElement, and creates connections - * between those nodes so the first node will hold a reference to a second one, and a second node will hold - * a reference to the first one. - * - * @param firstElement any element of type T - * @param secondElement any element of type T - * @param generic type T - * @return a reference to the first node - */ - public static Node closedPairOf(T firstElement, T secondElement) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates a linked chain of {@link Node} objects based on provided elements. Creates a connection between those - * nodes so each node will hold a reference to the next one in the chain. HINT: it's basically a linked list. - * - * @param elements a array of elements of type T - * @param generic type T - * @return a reference to the first element of the chain - */ - public static Node chainOf(T... elements) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates a linked circle of {@link Node} objects based on provided elements. Creates a connection between those - * nodes so each node will hold a reference to the next one in the chain, and the last one will hold a reference to - * the first one. - * - * @param elements a array of elements of type T - * @param generic type T - * @return a reference to the first element of the chain - */ - public static Node circleOf(T... elements) { - throw new ExerciseNotCompletedException(); // todo: - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-1-node/src/test/java/com/bobocode/cs/NodesTest.java b/2-0-data-structures-and-algorithms/2-2-1-node/src/test/java/com/bobocode/cs/NodesTest.java deleted file mode 100644 index e4c020ee8..000000000 --- a/2-0-data-structures-and-algorithms/2-2-1-node/src/test/java/com/bobocode/cs/NodesTest.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.bobocode.cs; - -import com.bobobode.cs.Node; -import com.bobobode.cs.Nodes; -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.Arrays; - -import static org.assertj.core.api.Assertions.assertThat; - -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class NodesTest { - - @Test - @Order(1) - void create() { - int element = 5; - - Node node = Nodes.create(element); - - assertThat(getNodeElement(node)).isEqualTo(element); - assertThat(getNodeNext(node)).isNull(); - } - - @Test - @Order(2) - void link() { - Node firstNode = createNodeOf(5); - Node secondNode = createNodeOf(9); - Node thirdNode = createNodeOf(100); - setNodeNext(secondNode, thirdNode); - - Nodes.link(firstNode, secondNode); - - assertThat(getNodeNext(firstNode)).isEqualTo(secondNode); - assertThat(getNodeNext(secondNode)).isEqualTo(thirdNode); - } - - @Test - @Order(3) - void pair() { - int firstElement = 8; - int secondElement = 2; - - Node firstNode = Nodes.pairOf(firstElement, secondElement); - - Node secondNode = getNodeNext(firstNode); - assertThat(getNodeElement(firstNode)).isEqualTo(firstElement); - assertThat(getNodeElement(secondNode)).isEqualTo(secondElement); - assertThat(getNodeNext(secondNode)).isNull(); - } - - @Test - @Order(4) - void closedPair() { - int firstElement = 8; - int secondElement = 2; - - Node firstNode = Nodes.closedPairOf(firstElement, secondElement); - - Node secondNode = getNodeNext(firstNode); - assertThat(getNodeElement(firstNode)).isEqualTo(firstElement); - assertThat(getNodeElement(secondNode)).isEqualTo(secondElement); - assertThat(getNodeNext(secondNode)).isEqualTo(firstNode); - } - - @Test - @Order(5) - void chain() { - int firstElement = 8; - int secondElement = 1; - int thirdElement = 13; - int fourthElement = 5; - - Node firstNode = Nodes.chainOf(firstElement, secondElement, thirdElement, fourthElement); - - Node secondNode = getNodeNext(firstNode); - Node thirdNode = getNodeNext(secondNode); - Node fourthNode = getNodeNext(thirdNode); - assertThat(getNodeElement(firstNode)).isEqualTo(firstElement); - assertThat(getNodeElement(secondNode)).isEqualTo(secondElement); - assertThat(getNodeElement(thirdNode)).isEqualTo(thirdElement); - assertThat(getNodeElement(fourthNode)).isEqualTo(fourthElement); - assertThat(getNodeNext(fourthNode)).isNull(); - } - - @Test - @Order(6) - void circle() { - int firstElement = 8; - int secondElement = 1; - int thirdElement = 13; - int fourthElement = 5; - - Node firstNode = Nodes.circleOf(firstElement, secondElement, thirdElement, fourthElement); - - Node secondNode = getNodeNext(firstNode); - Node thirdNode = getNodeNext(secondNode); - Node fourthNode = getNodeNext(thirdNode); - assertThat(getNodeElement(firstNode)).isEqualTo(firstElement); - assertThat(getNodeElement(secondNode)).isEqualTo(secondElement); - assertThat(getNodeElement(thirdNode)).isEqualTo(thirdElement); - assertThat(getNodeElement(fourthNode)).isEqualTo(fourthElement); - assertThat(getNodeNext(fourthNode)).isEqualTo(firstNode); - } - - @SneakyThrows - @SuppressWarnings("unchecked") - private Node createNodeOf(int element) { - Constructor constructor = Arrays.stream(Node.class.getDeclaredConstructors()) - .findAny() - .orElseThrow(); - constructor.setAccessible(true); - Node node; - if (constructor.getParameters().length > 0) { - node = (Node) constructor.newInstance(element); - } else { - node = (Node) constructor.newInstance(); - setNodeElement(node, element); - } - return node; - } - - @SneakyThrows - @SuppressWarnings("unchecked") - private T getNodeElement(Node node) { - Field elementField = getAccessibleElementField(); - return (T) elementField.get(node); - } - - @SneakyThrows - private void setNodeElement(Node node, T element) { - Field elementField = getAccessibleElementField(); - elementField.set(node, element); - } - - @SneakyThrows - @SuppressWarnings("unchecked") - private Node getNodeNext(Node node) { - Field nextField = getAccessibleNextField(); - return (Node) nextField.get(node); - } - - @SneakyThrows - private void setNodeNext(Node node, Node next) { - Field elementField = getAccessibleNextField(); - elementField.set(node, next); - } - - private Field getAccessibleElementField() { - Field elementField = Arrays.stream(Node.class.getDeclaredFields()) - .filter(field -> field.getType().equals(Object.class)) - .findAny() - .orElseThrow(); - elementField.setAccessible(true); - return elementField; - } - - private Field getAccessibleNextField() { - Field nextField = Arrays.stream(Node.class.getDeclaredFields()) - .filter(field -> field.getType().equals(Node.class)) - .findAny() - .orElseThrow(); - nextField.setAccessible(true); - return nextField; - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/README.md b/2-0-data-structures-and-algorithms/2-2-2-stack/README.md deleted file mode 100644 index fb740f365..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Stack 🥞 -Learn the Stack data structure and gain deep understanding implementing it on your own 💪 - - -### WHY ❓ -[Stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)) is one of the most important data structures -for software developers. It can be used in various algorithms, but the most important is that **JVM creates a stack -for each thread.** 😯 Even if you don't know anything about concurrency, and you write a simple application, it is still -**executed by one main thread.** So each thread has its own stack, and **that stack is used to store method frames.** 😲 -A [method frame](https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-2.html#jvms-2.6) is just a term. It simply -means all the information we operate with, when executing a method. E.g. **when you pass some arguments, or create -local variable, all that data is stored to the stack.** So, **every a method is called, a new stack frame is created and -stored to the stack.** - -> It is important to understand Stack, because otherwise you won't be able to understand fundamental things like **how JVM executes methods** and **how it uses memory**. - -### Objectives -* implement a generic class `Node` ✅ -* **push an element onto the stack** ✅ -* **get an element from the stack** ✅ -* maintain stack **size** ✅ - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/pom.xml b/2-0-data-structures-and-algorithms/2-2-2-stack/pom.xml deleted file mode 100644 index 1e7a91994..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-2-stack - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/LinkedStack.java b/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/LinkedStack.java deleted file mode 100644 index 05b0c724d..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/LinkedStack.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.cs.exception.EmptyStackException; -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link LinkedStack} is a stack implementation that is based on singly linked generic nodes. - * A node is implemented as inner static class {@link Node}. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @param generic type parameter - * @author Taras Boychuk - * @author Serhii Hryhus - */ -public class LinkedStack implements Stack { - - /** - * This method creates a stack of provided elements - * - * @param elements elements to add - * @param generic type - * @return a new stack of elements that were passed as method parameters - */ - public static LinkedStack of(T... elements) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * The method pushes an element onto the top of this stack. This has exactly the same effect as: - * addElement(item) - * - * @param element elements to add - */ - @Override - public void push(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * This method removes the object at the top of this stack - * and returns that object as the value of this function. - * - * @return The object at the top of this stack - * @throws EmptyStackException - if this stack is empty - */ - @Override - public T pop() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the number of elements in the stack - * - * @return number of elements - */ - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks if a stack is empty - * - * @return {@code true} if a stack is empty, {@code false} otherwise - */ - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: implement this method; - } - -} diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/Stack.java b/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/Stack.java deleted file mode 100644 index bfa428ee7..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/Stack.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.bobocode.cs; - -/** - * {@link Stack} is a fundamental data structure that follows last-in-first-out (LIFO) principle. This interface - * represents a simple contact, that can be implemented in various ways (e.g. using existing collections, arrays or - * custom linked nodes) - * - * @param type parameter - * @author Taras Boychuk - * @author Serhii Hryhus - */ -public interface Stack { - - void push(T element); - - T pop(); - - int size(); - - boolean isEmpty(); -} diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/exception/EmptyStackException.java b/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/exception/EmptyStackException.java deleted file mode 100644 index d0cb33c91..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/src/main/java/com/bobocode/cs/exception/EmptyStackException.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.bobocode.cs.exception; - -public class EmptyStackException extends RuntimeException{ - -} diff --git a/2-0-data-structures-and-algorithms/2-2-2-stack/src/test/java/com/bobocode/cs/LinkedStackTest.java b/2-0-data-structures-and-algorithms/2-2-2-stack/src/test/java/com/bobocode/cs/LinkedStackTest.java deleted file mode 100644 index 0311fd1db..000000000 --- a/2-0-data-structures-and-algorithms/2-2-2-stack/src/test/java/com/bobocode/cs/LinkedStackTest.java +++ /dev/null @@ -1,414 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.cs.exception.EmptyStackException; -import lombok.SneakyThrows; -import org.junit.jupiter.api.*; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.function.Predicate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNullPointerException; -import static org.junit.jupiter.api.Assertions.assertThrows; - -/** - * A reflection-based test class for {@link LinkedStack}. - *

- * PLEASE NOTE: we use Reflection API only for learning purposes. It should NOT be used for production tests. - * - * @author Ivan Virchenko - * @author Taras Boychuk - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class LinkedStackTest { - private static final String PROPER_CLASSNAME = "Node"; - - private static final Predicate NODE_FIELD_PREDICATE = field -> - field.getType().getSimpleName().equals(PROPER_CLASSNAME) - && field.getName().toLowerCase().contains("head") - || field.getName().toLowerCase().contains("first"); - - private static final Predicate SIZE_FIELD_PREDICATE = field -> - field.getName().toLowerCase().contains("size"); - - private static final Predicate NODE_ELEMENT_FIELD_PREDICATE = field -> - field.getName().toLowerCase().contains("element") - || field.getName().toLowerCase().contains("value") - || field.getName().toLowerCase().contains("item"); - - private static final Predicate NODE_NEXT_FIELD_PREDICATE = field -> - field.getType().getSimpleName().equals(PROPER_CLASSNAME) - && field.getName().toLowerCase().contains("next"); - - private Stack intStack = new LinkedStack<>(); - - @Test - @Order(1) - @DisplayName("Inner class Node is created") - void checkProperInnerClassName() { - String name = getInnerClass().getSimpleName(); - assertThat(name).isEqualTo(PROPER_CLASSNAME); - } - - @Test - @Order(2) - @DisplayName("Class Node is a generic class") - void noteIsAGenericClass() { - var nodeTypeParams = getInnerClass().getTypeParameters(); - - assertThat(nodeTypeParams).hasSize(1); - } - - @Test - @Order(3) - @DisplayName("LinkedStack class has a field that stores a reference to the first(head) element") - void checkProperHeadFieldName() { - Field[] fields = LinkedStack.class.getDeclaredFields(); - - boolean hasNodeField = Arrays.stream(fields) - .anyMatch(NODE_FIELD_PREDICATE); - - assertThat(hasNodeField).isTrue(); - } - - @Test - @Order(4) - @DisplayName("LinkedStack class has a field to store stack size") - void checkProperSizeFieldName() { - Field[] fields = LinkedStack.class.getDeclaredFields(); - - boolean hasSizeField = Arrays.stream(fields) - .anyMatch(SIZE_FIELD_PREDICATE); - - assertThat(hasSizeField).isTrue(); - } - - @Test - @Order(5) - @DisplayName("Node class has a field to store a generic element") - void checkProperElementField() { - var fields = getInnerClass().getDeclaredFields(); - - var elementField = Arrays.stream(fields) - .filter(NODE_ELEMENT_FIELD_PREDICATE) - .findAny() - .orElseThrow(); - var nodeTypeParameter = getInnerClass().getTypeParameters()[0]; - - - assertThat(elementField.getGenericType().getTypeName()).isEqualTo(nodeTypeParameter.getTypeName()); - } - - @Test - @Order(6) - @DisplayName("Node class has a field to store a reference to the next node") - void checkProperNextField() { - Field[] fields = getInnerClass().getDeclaredFields(); - - boolean hasNext = Arrays.stream(fields) - .anyMatch(NODE_NEXT_FIELD_PREDICATE); - - assertThat(hasNext).isTrue(); - } - - @Test - @Order(7) - @DisplayName("Method of() creates a new LinkedStack of given elements") - void of() { - intStack = LinkedStack.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - - for (int i = 1; i <= 10; i++) { - assertThat(contains(i)).isTrue(); - } - } - - @Test - @Order(8) - @DisplayName("Method push() adds new element on top of the stack") - void push() { - intStack.push(55); - - assertThat(contains(55)).isTrue(); - } - - @Test - @Order(9) - @DisplayName("Method push() adds new element on top of the stack") - void pushAddsElementWhenStackIsEmpty() { - intStack.push(243); - - assertThat(contains(243)).isTrue(); - } - - @Test - @Order(10) - @DisplayName("Method push() adds new element on top of the stack when it's empty") - void pushAddsElementToHeadWhenStackIsEmpty() { - intStack.push(10); - - Object head = getHeadObject(); - int innerElement = getNodeElementInt(head); - - assertThat(innerElement).isEqualTo(10); - } - - @Test - @Order(11) - @DisplayName("Method push() adds new element on top of the stack when it's not empty") - void pushAddsElementToHeadWhenStackIsNotEmpty() { - intStack.push(10); - intStack.push(15); - intStack.push(20); - - Object head = getHeadObject(); - int innerElement = getNodeElementInt(head); - - assertThat(innerElement).isEqualTo(20); - } - - @Test - @Order(12) - @DisplayName("Method push() links new element with the previous top (head) element") - void pushPutsHeadToNextOfNewHead() { - fillTestStack(10, 15, 20); - - assertThat(getNodeElementInt(getHeadObject())).isEqualTo(20); - - intStack.push(30); - - Object head = getHeadObject(); - Object next = getNodeNextObject(head); - int nextElement = getNodeElementInt(next); - - assertThat(nextElement).isEqualTo(20); - } - - @Test - @Order(13) - @DisplayName("Method push() throws exception when element is null") - void pushThrowsExceptionWhenElementIsNull() { - assertThatNullPointerException().isThrownBy(() -> intStack.push(null)); - } - - @Test - @Order(14) - @DisplayName("Method pop() throws exception when stack is empty") - void popElementWhenStackIsEmpty() { - assertThrows(EmptyStackException.class, () -> intStack.pop()); - } - - @Test - @Order(15) - @DisplayName("Method pop() retrieves top element from the stack (LIFO)") - void pop() { - fillTestStack(55, 17, 66, 234); - - int lastElement = intStack.pop(); - - assertThat(lastElement).isEqualTo(234); - } - - @Test - @Order(16) - @DisplayName("Method pop() assigns next element to be a head") - void popResetsHeadFromNextOfOldHead() { - fillTestStack(10, 15, 20); - Object head = getHeadObject(); - - assertThat(getNodeElementInt(head)).isEqualTo(20); - - intStack.pop(); - head = getHeadObject(); - - assertThat(getNodeElementInt(head)).isEqualTo(15); - } - - @Test - @Order(17) - @DisplayName("Method size() returns 0 when stack is empty") - void sizeWhenStackIsEmpty() { - int actualSize = getInnerSize(); - - assertThat(actualSize).isEqualTo(0); - } - - @Test - @Order(18) - @DisplayName("Method size() returns number of element in the stack") - void size() { - fillTestStack(1, 5, 7); - - assertThat(intStack.size()).isEqualTo(3); - } - - @Test - @Order(19) - @DisplayName("Method size() returns correct value when stack was created via method of()") - void sizeIncreasesWhenUseOfMethod() { - intStack = LinkedStack.of(1, 2, 3, 4, 5, 6, 7, 8); - - assertThat(intStack.size()).isEqualTo(8); - } - - @Test - @Order(20) - @DisplayName("Method size() correct value when elements were added via push()") - void sizeIncreasesWhenPush() { - intStack.push(1); - intStack.push(2); - intStack.push(3); - - assertThat(intStack.size()).isEqualTo(3); - } - - @Test - @Order(21) - @DisplayName("Method size() correct value when elements were removed via pop()") - void sizeDecreasesWhenPop() { - fillTestStack(1, 2, 3, 4, 5); - intStack.pop(); - - assertThat(intStack.size()).isEqualTo(4); - } - - @Test - @Order(22) - @DisplayName("Method isEmpty() returns true when stack contains elements") - void isEmpty() { - fillTestStack(87, 53, 66); - - boolean stackEmpty = intStack.isEmpty(); - - assertThat(stackEmpty).isEqualTo(false); - } - - @Test - @Order(23) - @DisplayName("Method isEmpty() returns false when stack contains no elements") - void isEmptyWhenStackIsEmpty() { - boolean stackEmpty = intStack.isEmpty(); - assertThat(stackEmpty).isEqualTo(true); - } - - private Class getInnerClass() { - return Arrays.stream(LinkedStack.class.getDeclaredClasses()) - .filter(Class::isMemberClass) - .findAny().orElseThrow(); - } - - private Field getHeadField() { - Field headField = Arrays.stream(LinkedStack.class.getDeclaredFields()) - .filter(NODE_FIELD_PREDICATE) - .findAny() - .orElseThrow(); - headField.setAccessible(true); - return headField; - } - - private Field getNodeElementField(Object node) { - Field fieldElement = Arrays.stream(node.getClass().getDeclaredFields()) - .filter(NODE_ELEMENT_FIELD_PREDICATE) - .findAny() - .orElseThrow(); - fieldElement.setAccessible(true); - return fieldElement; - } - - private Field getNodeNextField(Object node) { - Field field = Arrays.stream(node.getClass().getDeclaredFields()) - .filter(NODE_NEXT_FIELD_PREDICATE) - .findAny() - .orElseThrow(); - field.setAccessible(true); - return field; - } - - @SneakyThrows - private Object getHeadObject() { - return getHeadField().get(intStack); - } - - @SneakyThrows - private int getNodeElementInt(Object node) { - return (int) getNodeElementField(node).get(node); - } - - @SneakyThrows - private Object getNodeNextObject(Object node) { - return getNodeNextField(node).get(node); - } - - private boolean contains(int element) { - Object head = getHeadObject(); - if (head == null) { - return false; - } - - if (getNodeNextObject(head) != null) { - return checkNext(head, element); - } else { - return getNodeElementInt(head) == element; - } - } - - private boolean checkNext(Object node, int element) { - if (getNodeElementInt(node) == element) { - return true; - } else { - return checkNext(getNodeNextObject(node), element); - } - } - - @SneakyThrows - private Object newNode(int element) { - Constructor constructor = getInnerClass().getDeclaredConstructors()[0]; - constructor.setAccessible(true); - - if (constructor.getParameters().length == 1) { - return constructor.newInstance(element); - } else if (constructor.getParameters().length == 2) { - return constructor.newInstance(element, null); - } else { - Object node = constructor.newInstance(); - getNodeElementField(node).set(node, element); - return node; - } - } - - private void fillTestStack(int... elements) { - for (int element : elements) { - addToStack(element); - } - setInnerSize(elements.length); - } - - @SneakyThrows - private void addToStack(int element) { - Object newNode = newNode(element); - if (getHeadObject() != null) { - getNodeNextField(newNode).set(newNode, getHeadObject()); - } - getHeadField().set(intStack, newNode); - } - - private Field getInnerSizeField() { - Field size = Arrays.stream(LinkedStack.class.getDeclaredFields()) - .filter(SIZE_FIELD_PREDICATE) - .findAny() - .orElseThrow(); - size.setAccessible(true); - return size; - } - - @SneakyThrows - private void setInnerSize(int size) { - getInnerSizeField().set(intStack, size); - } - - @SneakyThrows - private int getInnerSize() { - return (int) getInnerSizeField().get(intStack); - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/README.MD b/2-0-data-structures-and-algorithms/2-2-3-linked-queue/README.MD deleted file mode 100644 index a5419bbae..000000000 --- a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/README.MD +++ /dev/null @@ -1,17 +0,0 @@ -# Linked Queue -Learn the idea of a queue and build strong skills implementing a queue based on linked nodes 💪 - -### Pre-conditions ❗ -You're supposed to be familiar [Queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) data structure and generics in Java - -### Objectives -* implement a generic class `Node` ✅ -* **add an element** to the end of the queue ✅ -* **retrieve an element** from the begging of the queue ** ✅ -* maintain queue **size** ✅ - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/pom.xml b/2-0-data-structures-and-algorithms/2-2-3-linked-queue/pom.xml deleted file mode 100644 index 860b6ee24..000000000 --- a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-3-linked-queue - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/LinkedQueue.java b/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/LinkedQueue.java deleted file mode 100644 index 7b4a79667..000000000 --- a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/LinkedQueue.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link LinkedQueue} implements FIFO {@link Queue}, using singly linked nodes. Nodes are stores in instances of nested - * class Node. In order to perform operations {@link LinkedQueue#add(Object)} and {@link LinkedQueue#poll()} - * in a constant time, it keeps to references to the head and tail of the queue. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @param a generic parameter - * @author Taras Boychuk - * @author Ivan Virchenko - */ -public class LinkedQueue implements Queue { - - /** - * Adds an element to the end of the queue. - * - * @param element the element to add - */ - public void add(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Retrieves and removes queue head. - * - * @return an element that was retrieved from the head or null if queue is empty - */ - public T poll() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns a size of the queue. - * - * @return an integer value that is a size of queue - */ - public int size() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks if the queue is empty. - * - * @return {@code true} if the queue is empty, returns {@code false} if it's not - */ - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/Queue.java b/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/Queue.java deleted file mode 100644 index 4aa0a28d1..000000000 --- a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/main/java/com/bobocode/cs/Queue.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.bobocode.cs; - -/** - * Queue is a data structure that follows "first in, first out" rule (FIFO). Operations {@link Queue#add(Object)} and - * {@link Queue#poll()} are performed in constant time O(1) - */ -public interface Queue { - /** - * Adds an element to the end of the queue. - * - * @param element the element to add - */ - void add(T element); - - /** - * Retrieves and removes queue head. - * - * @return an element that was retrieved from the head or null if queue is empty - */ - T poll(); - - /** - * Returns a size of the queue. - * - * @return an integer value that is a size of queue - */ - int size(); - - /** - * Checks if the queue is empty. - * - * @return {@code true} if the queue is empty, returns {@code false} if it's not - */ - boolean isEmpty(); -} diff --git a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/test/java/com/bobocode/cs/LinkedQueueTest.java b/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/test/java/com/bobocode/cs/LinkedQueueTest.java deleted file mode 100644 index 88c1a7d9d..000000000 --- a/2-0-data-structures-and-algorithms/2-2-3-linked-queue/src/test/java/com/bobocode/cs/LinkedQueueTest.java +++ /dev/null @@ -1,377 +0,0 @@ -package com.bobocode.cs; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.function.Predicate; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * A reflection-based test class for {@link LinkedQueue}. - *

- * PLEASE NOTE: we use Reflection API only for learning purposes. It should NOT be used for production tests. - * - * @author Victor Kuzma - * @author Taras Boychuk - * @author Ivan Virchenko - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class LinkedQueueTest { - private static final String NODE_NAME = "Node"; - private static final String SIZE_NAME = "size"; - - private static final Predicate NODE_FIELD = field -> - field.getType().getSimpleName().equals(NODE_NAME) && (field.getName().contains("next")); - - private static final Predicate ELEMENT_FIELD = field -> - field.getGenericType().getTypeName().equals("T") - && (field.getName().contains("elem") || field.getName().contains("value") || field.getName().contains("item")); - - private static final Predicate NEXT_FIELD = field -> - field.getGenericType().getTypeName().endsWith("Node") && (field.getName().contains("next")); - - private static final Predicate SIZE_FIELD = field -> - field.getType().getSimpleName().equals("int") && (field.getName().equals(SIZE_NAME)); - - private static final Predicate HEAD_FIELD = field -> - field.getType().getSimpleName().equals(NODE_NAME) - && (field.getName().contains("head") || field.getName().contains("first")); - - private static final Predicate TAIL_FIELD = field -> - field.getType().getSimpleName().equals(NODE_NAME) - && (field.getName().contains("tail") || field.getName().contains("last")); - - private Queue integerQueue = new LinkedQueue<>(); - - @Test - @Order(1) - void createNodeClass() { - Class innerClass = getInnerStaticNodeClass(); - String name = innerClass.getSimpleName(); - - assertThat(name).isEqualTo(NODE_NAME); - } - - @Test - @Order(2) - void checkFieldsNameInNodeClass() { - Class innerClass = getInnerStaticNodeClass(); - boolean hasElementField = hasField(innerClass, ELEMENT_FIELD); - boolean hasNodeField = hasField(innerClass, NODE_FIELD); - - assertThat(hasElementField).isTrue(); - assertThat(hasNodeField).isTrue(); - } - - @Test - @Order(3) - void checkFieldsInQueueCLass() { - Class baseClass = this.integerQueue.getClass(); - boolean hasHeadField = hasField(baseClass, HEAD_FIELD); - boolean hasSizeFiled = hasField(baseClass, SIZE_FIELD); - boolean hasTailFiled = hasField(baseClass, TAIL_FIELD); - - assertThat(hasHeadField).isTrue(); - assertThat(hasSizeFiled).isTrue(); - assertThat(hasTailFiled).isTrue(); - } - - @Test - @Order(4) - void addFillsQueueWhenItIsEmpty() { - integerQueue.add(1); - integerQueue.add(228); - int size = getInternalSize(); - boolean isEmpty = isEmptyQueue(); - Integer firstElement = (Integer) pollElementFromQueue(); - Integer secondElement = (Integer) pollElementFromQueue(); - - assertThat(size).isEqualTo(2); - assertThat(isEmpty).isEqualTo(false); - assertThat(firstElement).isEqualTo(1); - assertThat(secondElement).isEqualTo(228); - } - - @Test - @Order(5) - void addFillsQueueWhenItIsNotEmpty() { - addIntElementToQueue(12); - addIntElementToQueue(13); - integerQueue.add(111); - int size = getInternalSize(); - boolean isEmpty = isEmptyQueue(); - Integer firstElement = (Integer) pollElementFromQueue(); - Integer secondElement = (Integer) pollElementFromQueue(); - Integer tailValue = (Integer) getNodeValue(TAIL_FIELD); - - assertThat(size).isEqualTo(3); - assertThat(isEmpty).isEqualTo(false); - assertThat(firstElement).isEqualTo(12); - assertThat(secondElement).isEqualTo(13); - assertThat(tailValue).isEqualTo(111); - } - - @Test - @Order(6) - void addIncreasesQueueSize() { - integerQueue.add(1); - integerQueue.add(2); - int size = getInternalSize(); - - assertThat(size).isEqualTo(2); - } - - @Test - @Order(7) - void pollReturnsNullWhenQueueIsEmpty() { - Integer firstElement = this.integerQueue.poll(); - - assertThat(firstElement).isEqualTo(null); - } - - @Test - @Order(8) - void pollDeletesElementFromHead() { - addIntElementToQueue(11); - addIntElementToQueue(111); - Integer firstElement = this.integerQueue.poll(); - Integer secondElement = this.integerQueue.poll(); - boolean isEmpty = isEmptyQueue(); - - assertThat(isEmpty).isEqualTo(true); - assertThat(firstElement).isEqualTo(11); - assertThat(secondElement).isEqualTo(111); - } - - @Test - @Order(9) - void pollDecreasesQueueSize() { - addIntElementToQueue(11); - addIntElementToQueue(111); - this.integerQueue.poll(); - int size = getInternalSize(); - - assertThat(size).isEqualTo(1); - } - - @Test - @Order(10) - void pollMakesSizeZeroWhenQueueHasSingleElement() { - addIntElementToQueue(12); - Integer element = this.integerQueue.poll(); - int size = getInternalSize(); - - assertThat(size).isEqualTo(0); - assertThat(element).isEqualTo(12); - } - - @Test - @SneakyThrows - @Order(11) - void pollMakesQueueEmptyWhenQueueHasSingleElement() { - addIntElementToQueue(1); - this.integerQueue.poll(); - boolean isEmpty = isEmptyQueue(); - - Object tail = getAccessibleFieldByPredicate(integerQueue, TAIL_FIELD).get(integerQueue); - Object head = getAccessibleFieldByPredicate(integerQueue, HEAD_FIELD).get(integerQueue); - - assertThat(isEmpty).isEqualTo(true); - assertThat(tail).isNull(); - assertThat(head).isNull(); - } - - @Test - @Order(12) - void sizeReturnsZeroWhenQueueIsEmpty() { - int size = this.integerQueue.size(); - - assertThat(size).isEqualTo(0); - } - - @Test - @Order(13) - void size() { - addIntElementToQueue(1); - int size = this.integerQueue.size(); - - assertThat(size).isEqualTo(1); - } - - @Test - @Order(14) - void isEmptyReturnsTrueWhenQueueIsEmpty() { - boolean isEmpty = this.integerQueue.isEmpty(); - - assertThat(isEmpty).isEqualTo(true); - } - - @Test - @Order(15) - void isEmpty() { - addIntElementToQueue(1); - boolean isEmpty = integerQueue.isEmpty(); - - assertThat(isEmpty).isEqualTo(false); - } - - - private Class getInnerStaticNodeClass() { - return Arrays.stream(integerQueue.getClass().getDeclaredClasses()) - .filter(aClass -> Modifier.isStatic(aClass.getModifiers())) - .findAny() - .orElseThrow(); - } - - private boolean hasField(Class classToSearch, Predicate targetField) { - return Arrays.stream(classToSearch.getDeclaredFields()) - .anyMatch(targetField); - } - - @SneakyThrows - private int getInternalSize() { - return (int) getAccessibleFieldByPredicate(this.integerQueue, SIZE_FIELD) - .get(this.integerQueue); - } - - - @SneakyThrows - private Object pollElementFromQueue() { - Object element; - Object nextElement; - Object tail; - Object head = getAccessibleFieldByPredicate(this.integerQueue, - HEAD_FIELD) - .get(this.integerQueue); - - Integer size = (Integer) getAccessibleFieldByPredicate(this.integerQueue, - SIZE_FIELD) - .get(this.integerQueue); - - if (head != null) { - element = getAccessibleFieldByPredicate(head, ELEMENT_FIELD) - .get(head); - - nextElement = getAccessibleFieldByPredicate(head, NODE_FIELD) - .get(head); - - head = nextElement; - setHead(head); - - if (head == null) { - tail = null; - setTail(tail); - } - - if (size != null) { - int tmpInt = size; - tmpInt--; - setInternalSize(tmpInt); - } - - return element; - } else { - return null; - } - } - - @SneakyThrows - private void addIntElementToQueue(int value) { - Object newNode = createNode(value); - Object head = getAccessibleFieldByPredicate(this.integerQueue, HEAD_FIELD).get(this.integerQueue); - Object tail = getAccessibleFieldByPredicate(this.integerQueue, TAIL_FIELD).get(this.integerQueue); - Integer size = (Integer) getAccessibleFieldByPredicate(this.integerQueue, SIZE_FIELD).get(this.integerQueue); - - if (head == null) { - setHead(newNode); - } else { - setNextNode(tail, newNode); - } - setTail(newNode); - - if (size == null) { - setInternalSize(1); - } else { - int tmpInt = size; - tmpInt++; - setInternalSize(tmpInt); - } - } - - @SneakyThrows - private Object createNode(int value) { - Object nodeObject; - Class innerClass = getInnerStaticNodeClass(); - Constructor[] declaredConstructors = innerClass.getDeclaredConstructors(); - Constructor constructor = declaredConstructors[0]; - constructor.setAccessible(true); - - if (constructor.getParameterTypes().length == 1) { - nodeObject = constructor.newInstance(value); - } else { - nodeObject = constructor.newInstance(); - Field nodeElement = getAccessibleFieldByPredicate(nodeObject, ELEMENT_FIELD); - nodeElement.set(nodeObject, value); - } - - return nodeObject; - } - - @SneakyThrows - private boolean isEmptyQueue() { - Object head = getAccessibleFieldByPredicate(this.integerQueue, - HEAD_FIELD) - .get(this.integerQueue); - return head == null; - } - - @SneakyThrows - private void setInternalSize(int size) { - Field sizeField = getAccessibleFieldByPredicate(this.integerQueue, - SIZE_FIELD); - sizeField.setInt(this.integerQueue, size); - } - - @SneakyThrows - private void setHead(Object obj) { - Field head = getAccessibleFieldByPredicate(this.integerQueue, HEAD_FIELD); - head.set(this.integerQueue, obj); - } - - @SneakyThrows - private void setTail(Object obj) { - Field tail = getAccessibleFieldByPredicate(this.integerQueue, TAIL_FIELD); - tail.set(this.integerQueue, obj); - } - - @SneakyThrows - private void setNextNode(Object current, Object next) { - Field nodeNextField = getAccessibleFieldByPredicate(current, NEXT_FIELD); - nodeNextField.set(current, next); - } - - private Field getAccessibleFieldByPredicate(Object object, Predicate predicate) { - Field field = Arrays.stream(object.getClass().getDeclaredFields()) - .filter(predicate) - .findAny() - .orElseThrow(); - field.setAccessible(true); - return field; - } - - @SneakyThrows - private Object getNodeValue(Predicate predicate) { - Object field = getAccessibleFieldByPredicate(integerQueue, predicate).get(integerQueue); - final Field value = getAccessibleFieldByPredicate(field, ELEMENT_FIELD); - value.setAccessible(true); - return value.get(field); - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-4-linked-list/README.MD b/2-0-data-structures-and-algorithms/2-2-4-linked-list/README.MD deleted file mode 100644 index 7ef45a4bb..000000000 --- a/2-0-data-structures-and-algorithms/2-2-4-linked-list/README.MD +++ /dev/null @@ -1,22 +0,0 @@ -# Linked List -Build strong skills implementing a well known Linked List data structure 💪 - -### Pre-conditions ❗ -You're supposed to be familiar [Linked List](https://en.wikipedia.org/wiki/Linked_list) data structure and generics in Java - -### Objectives -* implement a generic class `Node` ✅ -* **add an element** to the end of the list in **O(1)** ✅ -* **add an element by index** (relink nodes when adding a new one inside the chain) ✅ -* **set element** by index (find the correct node by index starting from `head`) ✅ -* **remove element** by index (link prev and next nodes to get rid of the one that should be removed) ✅ -* maintain list **size** ✅ - -### Exercise overview 🇺🇦 -[![Watch the video](https://img.youtube.com/vi/knhSNO3bAHo/0.jpg)](https://www.youtube.com/watch?v=knhSNO3bAHo) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-4-linked-list/pom.xml b/2-0-data-structures-and-algorithms/2-2-4-linked-list/pom.xml deleted file mode 100644 index d6e007661..000000000 --- a/2-0-data-structures-and-algorithms/2-2-4-linked-list/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-4-linked-list - - - - - com.bobocode - data-structures-and-algorithms-util - 1.0-SNAPSHOT - - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/main/java/com/bobocode/cs/LinkedList.java b/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/main/java/com/bobocode/cs/LinkedList.java deleted file mode 100644 index 502fefbdf..000000000 --- a/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/main/java/com/bobocode/cs/LinkedList.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.bobocode.cs; - - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link LinkedList} is a list implementation that is based on singly linked generic nodes. A node is implemented as - * inner static class {@link Node}. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @param generic type parameter - * @author Taras Boychuk - * @author Serhii Hryhus - */ -public class LinkedList implements List { - - /** - * This method creates a list of provided elements - * - * @param elements elements to add - * @param generic type - * @return a new list of elements the were passed as method parameters - */ - public static LinkedList of(T... elements) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds an element to the end of the list. - * - * @param element element to add - */ - @Override - public void add(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds a new element to the specific position in the list. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index an index of new element - * @param element element to add - */ - @Override - public void add(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Changes the value of an list element at specific position. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index an position of element to change - * @param element a new element value - */ - @Override - public void set(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Retrieves an elements by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index element index - * @return an element value - */ - @Override - public T get(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the first element of the list. Operation is performed in constant time O(1) - * - * @return the first element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getFirst() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the last element of the list. Operation is performed in constant time O(1) - * - * @return the last element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getLast() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes an elements by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index element index - * @return deleted element - */ - @Override - public T remove(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - - /** - * Checks if a specific exists in he list - * - * @return {@code true} if element exist, {@code false} otherwise - */ - @Override - public boolean contains(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks if a list is empty - * - * @return {@code true} if list is empty, {@code false} otherwise - */ - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the number of elements in the list - * - * @return number of elements - */ - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes all list elements - */ - @Override - public void clear() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/test/java/com/bobocode/cs/LinkedListTest.java b/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/test/java/com/bobocode/cs/LinkedListTest.java deleted file mode 100644 index 3f9ec1f9d..000000000 --- a/2-0-data-structures-and-algorithms/2-2-4-linked-list/src/test/java/com/bobocode/cs/LinkedListTest.java +++ /dev/null @@ -1,614 +0,0 @@ -package com.bobocode.cs; - - -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.NoSuchElementException; -import java.util.function.Predicate; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; - -/** - * A reflection-based test class for {@link LinkedList}. - *

- * PLEASE NOTE: we use Reflection API only for learning purposes. It should NOT be used for production tests. - * - * @author Serhii Hryhus - * @author Taras Boychuk - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class LinkedListTest { - private static final Predicate NODE_FIELD = field -> - field.getType().getSimpleName().equals("Node"); - - private static final Predicate HEAD_NODE_FIELD = field -> - field.getType().getSimpleName().equals("Node") - && (field.getName().contains("head") || field.getName().contains("first")); - - private static final Predicate TAIL_NODE_FIELD = field -> - field.getType().getSimpleName().equals("Node") - && (field.getName().equals("tail") || field.getName().contains("last")); - - private static final Predicate SIZE_FIELD = field -> - field.getName().equals("size"); - - private static final Predicate ELEMENT_FIELD = field -> - field.getGenericType().getTypeName().equals("T") - && (field.getName().contains("elem") || field.getName().contains("value") || field.getName().contains("item")); - - private LinkedList intList = new LinkedList<>(); - - @Test - @Order(1) - void properNodeName() { - Class innerClass = getInnerClass(); - - String name = innerClass.getSimpleName(); - - assertThat(name).isEqualTo("Node"); - } - - @Test - @Order(2) - void properNodeFields() { - Class innerClass = getInnerClass(); - - boolean hasElementField = Arrays.stream(innerClass.getDeclaredFields()) - .anyMatch(ELEMENT_FIELD); - - boolean hasNodeField = Arrays.stream(innerClass.getDeclaredFields()) - .anyMatch(NODE_FIELD); - - assertThat(hasElementField).isTrue(); - assertThat(hasNodeField).isTrue(); - } - - private Class getInnerClass() { - return Arrays.stream(intList.getClass().getDeclaredClasses()) - .filter(aClass -> Modifier.isStatic(aClass.getModifiers())) - .findAny() - .orElseThrow(); - } - - @Test - @Order(3) - void addIntoEmptyList() { - intList.add(41); - - int element = getInternalElement(0); - - assertThat(element).isEqualTo(41); - } - - @Test - @Order(4) - void addIntoEmptyListChangesSize() { - intList.add(41); - - int size = getInternalSize(); - - assertThat(size).isEqualTo(1); - } - - @Test - @Order(5) - void add() { - intList.add(41); - intList.add(30); - intList.add(75); - - int firstElement = getInternalElement(0); - int secondElement = getInternalElement(1); - int thirdElement = getInternalElement(2); - - assertThat(firstElement).isEqualTo(41); - assertThat(secondElement).isEqualTo(30); - assertThat(thirdElement).isEqualTo(75); - } - - @Test - @Order(6) - void addChangesSize() { - intList.add(41); - intList.add(30); - intList.add(75); - - int size = getInternalSize(); - - assertThat(size).isEqualTo(3); - } - - @Test - @Order(7) - void addByIndex() { - addInternalElements(43, 5, 6, 8); - - int newElementIdx = 2; - intList.add(newElementIdx, 66); - - int elementByNewElementIndex = getInternalElement(newElementIdx); - int size = getInternalSize(); - - assertThat(elementByNewElementIndex).isEqualTo(66); - assertThat(getInternalElement(0)).isEqualTo(43); - assertThat(getInternalElement(1)).isEqualTo(5); - assertThat(getInternalElement(3)).isEqualTo(6); - assertThat(getInternalElement(4)).isEqualTo(8); - assertThat(size).isEqualTo(5); - } - - @Test - @Order(8) - void addByZeroIndexWhenListIsEmpty() { - intList.add(0, 45); - - int element = getInternalElement(0); - int size = getInternalSize(); - - assertThat(element).isEqualTo(45); - assertThat(size).isEqualTo(1); - } - - @Test - @Order(9) - void addByIndexToTheEndOfList() { - addInternalElements(98, 64, 23, 1, 3, 4); - - int newElementIndex = getInternalSize(); - intList.add(newElementIndex, 44); - - assertThat(getInternalElement(newElementIndex)).isEqualTo(44); - assertThat(getInternalSize()).isEqualTo(7); - } - - @Test - @Order(10) - void addToHeadWhenListIsNotEmpty() { - addInternalElements(4, 6, 8, 9, 0, 2); - - intList.add(0, 53); - - int firstElement = getInternalElement(0); - int secondElement = getInternalElement(1); - int size = getInternalSize(); - - assertThat(firstElement).isEqualTo(53); - assertThat(secondElement).isEqualTo(4); - assertThat(size).isEqualTo(7); - } - - @Test - @Order(11) - void addThrowsExceptionWhenIndexIsNegative() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.add(-1, 66)); - } - - @Test - @Order(12) - void addThrowsExceptionWhenIndexLargerThanSize() { - addInternalElements(4, 6, 11, 9); - - int newElementIdx = 5; - - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.add(newElementIdx, 88)); - } - - @Test - @Order(13) - void addWhenIndexEqualToSize() { - addInternalElements(1, 2, 3, 4, 5); // size = 5 - - intList.add(5, 111); - - int element = getInternalElement(5); - int size = getInternalSize(); - - assertThat(element).isEqualTo(111); - assertThat(size).isEqualTo(6); - } - - @Test - @Order(14) - void of() { - intList = LinkedList.of(43, 233, 54); - - assertThat(getInternalElement(0)).isEqualTo(43); - assertThat(getInternalElement(1)).isEqualTo(233); - assertThat(getInternalElement(2)).isEqualTo(54); - } - - @Test - @Order(15) - void ofChangeSize() { - intList = LinkedList.of(43, 233, 54); - - int size = getInternalSize(); - - assertThat(size).isEqualTo(3); - } - - @Test - @Order(16) - void setByIndex() { - addInternalElements(34, 78, 9, 8); - - int index = 2; //element = 78 - intList.set(index, 99); - - int elementOnNewElementIndex = getInternalElement(index); - int nextElementToNewElementIndex = getInternalElement(3); - int internalSize = getInternalSize(); - - assertThat(elementOnNewElementIndex).isEqualTo(99); - assertThat(nextElementToNewElementIndex).isEqualTo(8); - assertThat(getInternalElement(0)).isEqualTo(34); - assertThat(getInternalElement(1)).isEqualTo(78); - assertThat(internalSize).isEqualTo(4); - } - - @Test - @Order(17) - void setFirstElementWhenListIsEmpty() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.set(0, 34)); - } - - @Test - @Order(18) - void setByIndexEqualToSize() { - addInternalElements(2, 3, 4); // size = 3 - - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.set(3, 222)); - } - - @Test - @Order(19) - void get() { - addInternalElements(25, 87, 45); - - int firstElement = intList.get(0); - int secondElement = intList.get(1); - int thirdElement = intList.get(2); - - assertThat(firstElement).isEqualTo(25); - assertThat(secondElement).isEqualTo(87); - assertThat(thirdElement).isEqualTo(45); - - } - - @Test - @Order(20) - void getByZeroIndexWhenListHasSingleElement() { - addInternalElements(25); - - int element = intList.get(0); - - assertThat(element).isEqualTo(25); - } - - @Test - @Order(21) - void getByZeroIndexWhenListIsEmpty() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.get(0)); - } - - @Test - @Order(22) - void getWhenIndexIsNegative() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.get(-1)); - } - - @Test - @Order(23) - void getWhenIndexIsEqualToListSize() { - addInternalElements(33, 46, 25, 87, 45); - - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.get(5)); - } - - @Test - @Order(24) - void getFirst() { - addInternalElements(31, 32, 5); - - int firstElement = intList.getFirst(); - - assertThat(firstElement).isEqualTo(31); - } - - @Test - @Order(25) - void getLast() { - addInternalElements(41, 6, 42); - - int lastElement = intList.getLast(); - - assertThat(lastElement).isEqualTo(42); - } - - @Test - @Order(26) - void getFirstWhenListIsEmpty() { - assertThatExceptionOfType(NoSuchElementException.class) - .isThrownBy(() -> intList.getFirst()); - } - - @Test - @Order(27) - void getLastWhenListIsEmpty() { - assertThatExceptionOfType(NoSuchElementException.class) - .isThrownBy(() -> intList.getLast()); - } - - - @Test - @Order(28) - void remove() { - addInternalElements(1, 2, 3, 4, 5); - - int elementIndex = 2; - int deletedElement = intList.remove(elementIndex); // element = 3 - - int replacedElement = getInternalElement(elementIndex); - - assertThat(deletedElement).isEqualTo(3); - assertThat(replacedElement).isEqualTo(4); - } - - @Test - @Order(29) - void removeChangesSize() { - addInternalElements(1, 2, 3, 4, 5); - - int elementIndex = 2; - int deletedElement = intList.remove(elementIndex); // element = 3 - - int size = getInternalSize(); - - assertThat(deletedElement).isEqualTo(3); - assertThat(size).isEqualTo(4); - } - - @Test - @Order(30) - void removeFirst() { - addInternalElements(4, 6, 8, 9); - - int deletedElement = intList.remove(0); - - int replacedElement = getInternalElement(0); - int size = getInternalSize(); - - assertThat(deletedElement).isEqualTo(4); - assertThat(replacedElement).isEqualTo(6); - assertThat(size).isEqualTo(3); - } - - @Test - @Order(31) - void removeLast() { - addInternalElements(4, 6, 8, 9); - - int deletedElement = intList.remove(getInternalSize() - 1); - - int newLastElement = getInternalElement(getInternalSize() - 1); - int tailElement = (int) getNodeValue(TAIL_NODE_FIELD); - - int size = getInternalSize(); - - assertThat(deletedElement).isEqualTo(9); - assertThat(newLastElement).isEqualTo(8); - assertThat(tailElement).isEqualTo(8); - assertThat(size).isEqualTo(3); - } - - @Test - @Order(32) - void removeWhenListIsEmpty() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.remove(234)); - } - - @Test - @Order(33) - void removeByZeroIndexWhenListIsEmpty() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> intList.remove(0)); - } - - @Test - @Order(34) - void size() { - setInternalSize(5); - - int sizeFromMethod = intList.size(); - - assertThat(sizeFromMethod).isEqualTo(5); - } - - @Test - @Order(35) - void sizeWhenListIsEmpty() { - int size = getInternalSize(); - - assertThat(size).isEqualTo(0); - } - - @Test - @Order(36) - void contains() { - addInternalElements(45, 6, 3, 6); - - boolean containsExistingElement = intList.contains(3); - boolean containsNotExistingElement = intList.contains(54); - - assertThat(containsExistingElement).isTrue(); - assertThat(containsNotExistingElement).isFalse(); - } - - @Test - @Order(37) - void containsWhenListIsEmpty() { - boolean contains = intList.contains(34); - - assertThat(contains).isFalse(); - } - - @Test - @Order(38) - void isEmpty() { - addInternalElements(34, 5, 6); - - boolean empty = intList.isEmpty(); - - assertThat(empty).isFalse(); - } - - @Test - @Order(39) - void isEmptyWhenListIsEmpty() { - boolean empty = intList.isEmpty(); - - assertThat(empty).isTrue(); - } - - @Test - @Order(40) - void clearWhenListIsEmpty() { - intList.clear(); - - int size = getInternalSize(); - - assertThat(size).isEqualTo(0); - } - - @Test - @Order(41) - void clearChangesSize() { - addInternalElements(4, 5, 6); - - intList.clear(); - - int size = getInternalSize(); - - assertThat(size).isEqualTo(0); - } - - @Test - @Order(42) - void clearRemovesAllElements() { - addInternalElements(4, 5, 6); - - intList.clear(); - - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(() -> getInternalElement(0)); - } - - @SneakyThrows - private int getInternalElement(int index) { - - Object head = getAccessibleFieldByPredicate(intList, HEAD_NODE_FIELD).get(intList); - - for (int j = 0; j < index; j++) { - head = getAccessibleFieldByPredicate(head, NODE_FIELD).get(head); - } - return (int) getAccessibleFieldByPredicate(head, ELEMENT_FIELD).get(head); - } - - @SneakyThrows - private int getInternalSize() { - return (int) getAccessibleFieldByPredicate(intList, SIZE_FIELD).get(intList); - } - - @SneakyThrows - private void addInternalElements(int... elements) { - Field nodeField = getInternalHeadField(); - Field tailNode = getInternalTailField(); - Class nodeType = nodeField.getType(); - - Object previousObject = intList; - Object nodeObject = null; - - for (int element : elements) { - nodeObject = createNodeObjectWithInternalElement(nodeType, element); - nodeField.set(previousObject, nodeObject); - nodeField = getAccessibleFieldByPredicate(nodeObject, NODE_FIELD); - previousObject = nodeObject; - } - - tailNode.set(intList, nodeObject); - setInternalSize(elements.length); - } - - private Field getInternalHeadField() { - return getAccessibleFieldByPredicate(intList, HEAD_NODE_FIELD); - } - - private Field getInternalTailField() { - return getAccessibleFieldByPredicate(intList, TAIL_NODE_FIELD); - } - - @SneakyThrows - private void setInternalSize(int size) { - Field sizeField = getAccessibleFieldByPredicate(intList, SIZE_FIELD); - sizeField.setInt(intList, size); - } - - @SneakyThrows - private Object createNodeObjectWithInternalElement(Class nodeClass, int element) { - Object nodeObject; - Constructor[] declaredConstructors = nodeClass.getDeclaredConstructors(); - Constructor constructor; - - constructor = declaredConstructors[0]; - constructor.setAccessible(true); - if (constructor.getParameterTypes().length == 1) { - nodeObject = constructor.newInstance(element); - } else { - nodeObject = createNodeByConstructorWithoutParameters(element, constructor); - } - return nodeObject; - } - - @SneakyThrows - private Object createNodeByConstructorWithoutParameters(int element, Constructor constructor) { - Object nodeObject; - nodeObject = constructor.newInstance(); - Field nodeElement = getAccessibleFieldByPredicate(nodeObject, ELEMENT_FIELD); - nodeElement.set(nodeObject, element); - return nodeObject; - } - - private Field getAccessibleFieldByPredicate(Object object, Predicate predicate) { - Field field = Arrays.stream(object.getClass().getDeclaredFields()) - .filter(predicate) - .findAny() - .orElseThrow(); - field.setAccessible(true); - return field; - } - - @SneakyThrows - private Object getNodeValue(Predicate predicate) { - Object field = getAccessibleFieldByPredicate(intList, predicate).get(intList); - final Field value = getAccessibleFieldByPredicate(field, ELEMENT_FIELD); - value.setAccessible(true); - return value.get(field); - } -} \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-5-array-list/README.MD b/2-0-data-structures-and-algorithms/2-2-5-array-list/README.MD deleted file mode 100644 index 8b925f53a..000000000 --- a/2-0-data-structures-and-algorithms/2-2-5-array-list/README.MD +++ /dev/null @@ -1,27 +0,0 @@ -# Array List - -Build strong skills implementing a well known Array List data structure 💪 - -### Pre-conditions ❗ - -* You're supposed to be familiar `List` collection and generics in Java - -### Objectives - -* use array of type `Object` to store any elements ✅ -* resize array using native method `System.arrayCopy()` ✅ -* **add an element** to the end of array ✅ -* **add an element by index** (shift whole array tail to the right) ✅ -* **set element** by index ✅ -* **remove element** by index (shift whole array tail to the left) ✅ -* maintain list **size** ✅ - -### Exercise overview 🇺🇦 -[![Watch the video](https://img.youtube.com/vi/jFBKToSC3ag/0.jpg)](https://www.youtube.com/watch?v=jFBKToSC3ag) - ---- - -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-5-array-list/pom.xml b/2-0-data-structures-and-algorithms/2-2-5-array-list/pom.xml deleted file mode 100644 index 7637723fb..000000000 --- a/2-0-data-structures-and-algorithms/2-2-5-array-list/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-5-array-list - - - - - com.bobocode - data-structures-and-algorithms-util - 1.0-SNAPSHOT - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-5-array-list/src/main/java/com/bobocode/cs/ArrayList.java b/2-0-data-structures-and-algorithms/2-2-5-array-list/src/main/java/com/bobocode/cs/ArrayList.java deleted file mode 100644 index 384ca81e5..000000000 --- a/2-0-data-structures-and-algorithms/2-2-5-array-list/src/main/java/com/bobocode/cs/ArrayList.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link ArrayList} is an implementation of {@link List} interface. This resizable data structure - * based on an array and is simplified version of {@link java.util.ArrayList}. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @author Serhii Hryhus - */ -public class ArrayList implements List { - - /** - * This constructor creates an instance of {@link ArrayList} with a specific capacity of an array inside. - * - * @param initCapacity - the initial capacity of the list - * @throws IllegalArgumentException – if the specified initial capacity is negative or 0. - */ - public ArrayList(int initCapacity) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * This constructor creates an instance of {@link ArrayList} with a default capacity of an array inside. - * A default size of inner array is 5; - */ - public ArrayList() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Creates and returns an instance of {@link ArrayList} with provided elements - * - * @param elements to add - * @return new instance - */ - public static List of(T... elements) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds an element to the array. - * - * @param element element to add - */ - @Override - public void add(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds an element to the specific position in the array where - * - * @param index index of position - * @param element element to add - */ - @Override - public void add(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Retrieves an element by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index index of element - * @return en element - */ - @Override - public T get(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the first element of the list. Operation is performed in constant time O(1) - * - * @return the first element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getFirst() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the last element of the list. Operation is performed in constant time O(1) - * - * @return the last element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getLast() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Changes the value of array at specific position. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index position of value - * @param element a new value - */ - @Override - public void set(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes an elements by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index element index - * @return deleted element - */ - @Override - public T remove(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks for existing of a specific element in the list. - * - * @param element is element - * @return If element exists method returns true, otherwise it returns false - */ - @Override - public boolean contains(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks if a list is empty - * - * @return {@code true} if list is empty, {@code false} otherwise - */ - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * @return amount of saved elements - */ - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes all list elements - */ - @Override - public void clear() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-5-array-list/src/test/java/com/bobocode/cs/ArrayListTest.java b/2-0-data-structures-and-algorithms/2-2-5-array-list/src/test/java/com/bobocode/cs/ArrayListTest.java deleted file mode 100644 index 3db9b465b..000000000 --- a/2-0-data-structures-and-algorithms/2-2-5-array-list/src/test/java/com/bobocode/cs/ArrayListTest.java +++ /dev/null @@ -1,406 +0,0 @@ -package com.bobocode.cs; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.lang.reflect.Field; -import java.util.NoSuchElementException; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; - -/** - * A reflection-based test class for {@link ArrayList}. - *

- * PLEASE NOTE: we use Reflection API only for learning purposes. It should NOT be used for production tests. - * - * @author Serhii Hryhus - * @author Ivan Virchenko - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class ArrayListTest { - - private List arrayList = new ArrayList<>(); - - @Test - @Order(1) - void add() { - arrayList.add(10); - arrayList.add(15); - arrayList.add(20); - - Object[] internalArray = getTestArray(); - - assertThat(internalArray[0]).isEqualTo(10); - assertThat(internalArray[1]).isEqualTo(15); - assertThat(internalArray[2]).isEqualTo(20); - } - - @Test - @Order(2) - void sizeOfEmptyArrayWrapper() { - assertThat(arrayList.size()).isEqualTo(0); - } - - @Test - @Order(3) - void size() { - setTestSize(3); - assertThat(arrayList.size()).isEqualTo(3); - } - - @Test - @Order(4) - void getElementsByIndex() { - fillTestArray(10, 15, 20); - - assertThat(arrayList.get(0)).isEqualTo(10); - assertThat(arrayList.get(1)).isEqualTo(15); - assertThat(arrayList.get(2)).isEqualTo(20); - assertThat(arrayList.size()).isEqualTo(3); - } - - @Test - @Order(5) - void getFirstElement() { - fillTestArray(31, 24); - assertThat(arrayList.getFirst()).isEqualTo(31); - } - - @Test - @Order(6) - void getLastElement() { - fillTestArray(31, 34); - assertThat(arrayList.getLast()).isEqualTo(34); - } - - @Test - @Order(7) - void getFirstOfEmptyList() { - assertThatExceptionOfType(NoSuchElementException.class) - .isThrownBy(() -> arrayList.getFirst()); - } - - @Test - @Order(8) - void getLastOfEmptyList() { - assertThatExceptionOfType(NoSuchElementException.class) - .isThrownBy(() -> arrayList.getLast()); - } - - @Test - @Order(9) - void createListWithSpecificArrayCapacity() { - arrayList = new ArrayList<>(8); - assertThat(getTestArray().length).isEqualTo(8); - } - - @Test - @Order(10) - void createListWithWrongCapacity() { - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> arrayList = new ArrayList<>(-2)); - } - - @Test - @Order(11) - void addElements() { - arrayList = ArrayList.of(15, 69, 58, 78); - - assertThat(getTestArray()[0]).isEqualTo(15); - assertThat(getTestArray()[1]).isEqualTo(69); - assertThat(getTestArray()[2]).isEqualTo(58); - assertThat(getTestArray()[3]).isEqualTo(78); - assertThat(getTestSize()).isEqualTo(4); - } - - @Test - @Order(12) - void addShouldResizeDefaultCapacityWhenArrayIsFull() { - arrayList = new ArrayList<>(); - int defaultCapacity = getTestArray().length; - - arrayList.add(15); - arrayList.add(69); - arrayList.add(58); - arrayList.add(78); - arrayList.add(6); - arrayList.add(33); - arrayList.add(21); - - assertThat(getTestArray().length).isGreaterThan(defaultCapacity); - assertThat(getTestSize()).isEqualTo(7); - } - - @Test - @Order(13) - void addShouldResizeSpecificCapacityWhenArrayIsFull() { - arrayList = new ArrayList<>(4); - - arrayList.add(15); - arrayList.add(69); - arrayList.add(58); - arrayList.add(78); - arrayList.add(6); - arrayList.add(33); - arrayList.add(21); - - assertThat(getTestArray().length).isGreaterThan(4); - assertThat(getTestSize()).isEqualTo(7); - } - - @Test - @Order(14) - void addElementByIndex() { - fillTestArray(15, 69, 58, 78, 68); - - arrayList.add(50); - arrayList.add(2, 10); - - Object[] internalArray = getTestArray(); - - assertThat(internalArray[2]).isEqualTo(10); - assertThat(internalArray[5]).isEqualTo(68); - assertThat(getTestSize()).isEqualTo(7); - } - - @Test - @Order(15) - void addElementByNegativeIndex() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.add(-1, 66)); - } - - @Test - @Order(16) - void addElementByIndexLargerThanListSize() { - setTestSize(4); - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.add(5, 88)); - } - - @Test - @Order(17) - void addElementByIndexEqualToSize() { - fillTestArray(1, 2, 3, 4, 5); - - arrayList.add(5, 111); - - Object[] internalArray = getTestArray(); - - assertThat(internalArray[5]).isEqualTo(111); - assertThat(getTestSize()).isEqualTo(6); - } - - @Test - @Order(18) - void getFirstElementFromEmptyList() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.get(0)); - } - - @Test - @Order(19) - void getElementByNegativeIndex() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.get(-1)); - } - - @Test - @Order(20) - void getElementByIndexThrowsExceptionWhenIndexIsOutOfBound() { - fillTestArray(1, 2, 3, 4); - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.get(4)); - } - - @Test - @Order(21) - void setElementByIndex() { - fillTestArray(15, 69, 58, 78); - Object[] internalArray = getTestArray(); - - arrayList.set(2, 10); - - assertThat(internalArray[2]).isEqualTo(10); - assertThat(internalArray[3]).isEqualTo(78); - assertThat(getTestSize()).isEqualTo(4); - } - - @Test - @Order(22) - void setElementByIndexThrowsExceptionWhenIndexIsOutOfBound() { - fillTestArray(15, 69, 58, 78); - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.set(4, 10)); - } - - @Test - @Order(23) - void setFirstElementOnEmptyList() { - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.set(0, 34)); - } - - @Test - @Order(24) - void removeElementByIndex() { - fillTestArray(15, 69, 58, 78, 100); - Object[] internalArray = getTestArray(); - - int removedElement = arrayList.remove(2); - - assertThat(internalArray[2]).isEqualTo(78); - assertThat(internalArray[1]).isEqualTo(69); - assertThat(getTestSize()).isEqualTo(4); - assertThat(removedElement).isEqualTo(58); - } - - @Test - @Order(25) - void removeElementByIndexThrowsExceptionWhenIndexEqualsSize() { - fillTestArray(15, 69, 58, 78); - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.remove(4)); - } - - @Test - @Order(26) - void removeLastElementByIndex() { - fillTestArray(15, 69, 58, 78, 100); - Object[] internalArray = getTestArray(); - - int removedElement = arrayList.remove(4); - - assertThat(internalArray[3]).isEqualTo(78); - assertThat(getTestSize()).isEqualTo(4); - assertThat(removedElement).isEqualTo(100); - } - - @Test - @Order(27) - void removeElementByIndexThrowsExceptionWhenIndexIsOutOfBounds() { - fillTestArray(15, 69, 58, 78, 100); - - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.remove(6)); - } - - @Test - @Order(28) - void containsOnEmptyList() { - assertThat(arrayList.contains(8)).isEqualTo(false); - } - - @Test - @Order(29) - void containsElement() { - fillTestArray(15, 69, 58, 78, 100); - assertThat(arrayList.contains(58)).isEqualTo(true); - } - - @Test - @Order(30) - void containsNotExistingWhenArrayIsNotFilled() { - arrayList = new ArrayList<>(100); - Object[] internalArray = getTestArray(); - internalArray[0] = 5; - internalArray[1] = 10; - - boolean result = arrayList.contains(3); - - assertThat(result).isFalse(); - } - - @Test - @Order(31) - void findNotExistingElement() { - fillTestArray(15, 69, 58, 78, 100); - assertThat(arrayList.contains(200)).isEqualTo(false); - } - - @Test - @Order(32) - void isEmptyOnEmptyList() { - assertThat(arrayList.isEmpty()).isEqualTo(true); - } - - @Test - @Order(33) - void isEmpty() { - setTestSize(3); - assertThat(arrayList.isEmpty()).isEqualTo(false); - } - - @Test - @Order(34) - void clearOnEmptyList() { - assertThat(arrayList.isEmpty()).isEqualTo(true); - } - - @Test - @Order(35) - void clearChangesTheSize() { - setTestSize(100); - arrayList.clear(); - - assertThat(arrayList.size()).isEqualTo(0); - } - - @Test - @Order(36) - void clearRemovesElements() { - fillTestArray(4, 5, 6); - - arrayList.clear(); - - assertThatExceptionOfType(IndexOutOfBoundsException.class) - .isThrownBy(() -> arrayList.get(0)); - } - - @SneakyThrows - private void setTestSize(int size) { - Field sizeField = arrayList.getClass().getDeclaredField("size"); - sizeField.setAccessible(true); - sizeField.set(arrayList, size); - } - - @SneakyThrows - private int getTestSize() { - Field testSize = arrayList.getClass().getDeclaredField("size"); - testSize.setAccessible(true); - return (int) testSize.get(arrayList); - } - - @SneakyThrows - private Object[] getTestArray() { - Field field = arrayList.getClass().getDeclaredField(getTestArrayName()); - field.setAccessible(true); - return (Object[]) field.get(arrayList); - } - - private String getTestArrayName() { - Field[] fields = arrayList.getClass().getDeclaredFields(); - String name = null; - for (Field field : fields) { - if (field.getType().isArray()) { - field.setAccessible(true); - name = field.getName(); - } - } - return name; - } - - @SneakyThrows - private void fillTestArray(Object... elements) { - Field arrayField = arrayList.getClass().getDeclaredField(getTestArrayName()); - Field sizeField = arrayList.getClass().getDeclaredField("size"); - arrayField.setAccessible(true); - sizeField.setAccessible(true); - arrayField.set(arrayList, elements); - sizeField.set(arrayList, elements.length); - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/README.md b/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/README.md deleted file mode 100644 index 4a86347ae..000000000 --- a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Binary Search Tree -Learn tree data structures and build strong skills implementing binary search tree using recursion 💪 - -### Pre-conditions ❗️ -* You're supposed to be familiar with trees like [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree) -* You should understand the [recursion](https://en.wikipedia.org/wiki/Recursion_(computer_science)) - -### Objectives -* implement a generic class `Node` with left and right child nodes ✅ -* **insert an element** to the tree using recursion ✅ -* **search an element** in the tree ✅ -* **traverse tree elements** in a ascending order ✅ -* calculate tree **depth** ✅ -* maintain tree **size** ✅ - - -### Exercise overview 🇺🇦 -[![Watch the video](https://img.youtube.com/vi/alxzyWswCVg/0.jpg)](https://www.youtube.com/watch?v=alxzyWswCVg) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/pom.xml b/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/pom.xml deleted file mode 100644 index ea8608159..000000000 --- a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-6-binary-search-tree - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/BinarySearchTree.java b/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/BinarySearchTree.java deleted file mode 100644 index d7462484d..000000000 --- a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/BinarySearchTree.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.bobocode.cs; - -import java.util.function.Consumer; - -public interface BinarySearchTree> { - /** - * insert an element - * @return true if element did not exist in the tree and was inserted successfully - */ - boolean insert(T element); - - /** - * @return true if tree contains element - */ - boolean contains(T element); - - /** - * @return number of elements in the tree - */ - int size(); - - /** - * @return max. number of transition between root node and any other node; 0 - if tree is empty or contains 1 element - */ - int depth(); - - /** - * traverse the tree in element's natural order - * @param consumer accepts ref. to node during traversing - */ - void inOrderTraversal(Consumer consumer); -} diff --git a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/RecursiveBinarySearchTree.java b/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/RecursiveBinarySearchTree.java deleted file mode 100644 index a4e394b0b..000000000 --- a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/main/java/com/bobocode/cs/RecursiveBinarySearchTree.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.util.ExerciseNotCompletedException; - -import java.util.function.Consumer; - -/** - * {@link RecursiveBinarySearchTree} is an implementation of a {@link BinarySearchTree} that is based on a linked nodes - * and recursion. A tree node is represented as a nested class {@link Node}. It holds an element (a value) and - * two references to the left and right child nodes. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @param a type of elements that are stored in the tree - * @author Taras Boychuk - * @author Maksym Stasiuk - */ -public class RecursiveBinarySearchTree> implements BinarySearchTree { - - public static > RecursiveBinarySearchTree of(T... elements) { - throw new ExerciseNotCompletedException(); - } - - @Override - public boolean insert(T element) { - throw new ExerciseNotCompletedException(); - } - - @Override - public boolean contains(T element) { - throw new ExerciseNotCompletedException(); - } - - @Override - public int size() { - throw new ExerciseNotCompletedException(); - } - - @Override - public int depth() { - throw new ExerciseNotCompletedException(); - } - - @Override - public void inOrderTraversal(Consumer consumer) { - throw new ExerciseNotCompletedException(); - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/test/java/com/bobocode/cs/RecursiveBinarySearchTreeTest.java b/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/test/java/com/bobocode/cs/RecursiveBinarySearchTreeTest.java deleted file mode 100644 index ac58a0b41..000000000 --- a/2-0-data-structures-and-algorithms/2-2-6-binary-search-tree/src/test/java/com/bobocode/cs/RecursiveBinarySearchTreeTest.java +++ /dev/null @@ -1,447 +0,0 @@ -package com.bobocode.cs; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNullPointerException; -import static org.junit.jupiter.params.provider.Arguments.arguments; - -/** - * A reflection-based test class for {@link ArrayList}. - *

- * PLEASE NOTE: we use Reflection API only for learning purposes. It should NOT be used for production tests. - * - * @author Ivan Virchenko - * @author Maksym Stasiuk - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class RecursiveBinarySearchTreeTest { - private static final Predicate SIZE_FIELD = field -> - field.getName().toLowerCase().contains("size") || field.getName().toLowerCase().contains("length"); - - private static final Predicate NODE_FIELD = field -> - field.getType().getSimpleName().equals("Node"); - - private static final Predicate ELEMENT_FIELD = field -> - field.getName().toLowerCase().contains("element") - || field.getName().toLowerCase().contains("item") - || field.getName().toLowerCase().contains("value"); - - private static final Predicate LEFT_FIELD = field -> - field.getName().toLowerCase().contains("left") - && field.getType().getSimpleName().equals("Node"); - - private static final Predicate RIGHT_FIELD = field -> - field.getName().toLowerCase().contains("right") - && field.getType().getSimpleName().equals("Node"); - - private static final Integer[] someElements = {10, 9, 11, 8, 12, 7}; - - private BinarySearchTree tree = new RecursiveBinarySearchTree<>(); - - @Test - @Order(1) - void properNodeClassNameCheck() { - Class innerClass = getInnerClass(); - String name = innerClass.getSimpleName(); - - assertThat(name).isEqualTo("Node"); - } - - @Test - @Order(2) - void properTreeFieldsCheck() { - Class treeClass = tree.getClass(); - - boolean hasSizeField = Arrays.stream(treeClass.getDeclaredFields()) - .anyMatch(SIZE_FIELD); - - boolean hasNodeField = Arrays.stream(treeClass.getDeclaredFields()) - .anyMatch(NODE_FIELD); - - assertThat(hasSizeField).isTrue(); - assertThat(hasNodeField).isTrue(); - } - - @Test - @Order(3) - void properNodeFieldsCheck() { - Class innerClass = getInnerClass(); - - boolean isElement = Arrays.stream(innerClass.getDeclaredFields()) - .anyMatch(ELEMENT_FIELD); - - boolean isLeft = Arrays.stream(innerClass.getDeclaredFields()) - .anyMatch(LEFT_FIELD); - - boolean isRight = Arrays.stream(innerClass.getDeclaredFields()) - .anyMatch(RIGHT_FIELD); - - assertThat(isElement).isTrue(); - assertThat(isLeft).isTrue(); - assertThat(isRight).isTrue(); - } - - @Test - @Order(4) - void of() { - tree = RecursiveBinarySearchTree.of(someElements); - for (var e : someElements) { - assertThat(contains(getRootObject(), e)).isTrue(); - } - assertThat(getInnerSize()).isEqualTo(someElements.length); - } - - @Test - @Order(5) - void insert() { - for (Integer e : someElements) { - assertThat(contains(getRootObject(), e)).isFalse(); //does not contain - assertThat(tree.insert(e)).isTrue(); //do insert - assertThat(contains(getRootObject(), e)).isTrue(); //and contains - } - } - - @Test - @Order(6) - void insertToRootIfTreeIsEmpty() { - assertThat(getRootObject()).isNull(); - tree.insert(10); - assertThat(getRootObject()).isNotNull(); - } - - @Test - @Order(7) - void insertLeftIfLessThanRoot() { - tree.insert(10); //root - tree.insert(5); //left - - assertThat(getLeftNode(getRootObject())).isNotNull(); - } - - @Test - @Order(8) - void insertRightIfGreaterThanRoot() { - tree.insert(10); //root - tree.insert(15); //right - - assertThat(getRightNode(getRootObject())).isNotNull(); - } - - @Test - @Order(9) - void insertDoesNotAddDuplicateElements() { - fillTestTree(10, 11, 12); - - assertThat(tree.insert(10)).isFalse(); - assertThat(tree.insert(11)).isFalse(); - assertThat(tree.insert(12)).isFalse(); - } - - @Test - @Order(10) - void insertThrowsExceptionWhenArgumentIsNull() { - fillTestTree(someElements); - assertThatNullPointerException().isThrownBy( - () -> tree.insert(null) - ); - } - - @Test - @Order(11) - void containsReturnsTrueIfElementExist() { - fillTestTree(9, 10, 11); - - assertThat(tree.contains(10)).isTrue(); - assertThat(tree.contains(9)).isTrue(); - assertThat(tree.contains(11)).isTrue(); - } - - @Test - @Order(12) - void containsReturnsFalseIfElementDoesntExist() { - fillTestTree(someElements); - assertThat(tree.contains(100)).isFalse(); - } - - @Test - @Order(13) - void containsThrowsExceptionIFParameterIsNull() { - assertThatNullPointerException().isThrownBy(() -> tree.contains(null)); - } - - @Test - @Order(14) - void sizeIsGrowingWhenInserting() { - tree.insert(10); - tree.insert(15); - tree.insert(20); - - assertThat(getInnerSize()).isEqualTo(3); - } - - @Test - @Order(15) - void sizeDoesNotGrowWhenInsertingNotUnique() { - fillTestTree(10, 11, 12); - - assertThat(getInnerSize()).isEqualTo(3); - - tree.insert(10); - tree.insert(11); - tree.insert(12); - - assertThat(getInnerSize()).isEqualTo(3); - } - - @Order(16) - @ParameterizedTest - @MethodSource("depthArguments") - void depth(Integer[] elements, int depth) { - fillTestTree(elements); - assertThat(tree.depth()).isEqualTo(depth); - } - - @Test - @Order(17) - void depthGrowWhenInsert() { - - tree.insert(13); - tree.insert(11); - tree.insert(12); - tree.insert(15); - tree.insert(-15); - - assertThat(tree.depth()).isGreaterThan(0); - } - - @Test - @Order(18) - void depthIsZeroIfRootIsNull() { - assertThat(tree.depth()).isEqualTo(0); - } - - @Test - @Order(19) - void inorderTraversal() { - fillTestTree(someElements); - Integer[] sortedElements = Arrays.copyOf(someElements, someElements.length); - Arrays.sort(sortedElements); - - List traversedElements = new ArrayList<>(getInnerSize()); - tree.inOrderTraversal(traversedElements::add); - - assertThat(traversedElements).isEqualTo(List.of(sortedElements)); - } - - public static Stream depthArguments() { - return Stream.of( - //empty tree - arguments(new Integer[]{}, 0), - //tree with a single element - arguments(new Integer[]{24}, 0), - /* - * .......10 - * ....../ \ - * .....5 15 - * ..../ \ - * ...1 20 - */ - arguments(new Integer[]{10, 5, 15, 1, 20}, 2), - /* - * ..1 - * ...\ - * ....2 - * .....\ - * ..... 3 - * .......\ - * ........4 - * .........\ - * ..........5 - */ - arguments(new Integer[]{1, 2, 3, 4, 5}, 4), - /* - * .........6 - * ....../.....\ - * .....2.......7 - * .../...\......\ - * ..1.....5......8 - * ......./........\ - * ......4..........9 - * ...../............. - * ....3............... - */ - arguments(new Integer[]{6, 2, 7, 1, 5, 8, 4, 9, 3}, 4)); - } - - - @SneakyThrows - private int getInnerSize() { - return (int) getInnerSizeField().get(tree); - } - - private Field getInnerSizeField() { - Field sizeField = Arrays.stream(tree.getClass().getDeclaredFields()) - .filter(SIZE_FIELD) - .findAny() - .orElseThrow(); - sizeField.setAccessible(true); - return sizeField; - } - - private Class getInnerClass() { - return Arrays.stream(tree.getClass().getDeclaredClasses()) - .filter(Class::isMemberClass) - .findAny() - .orElseThrow(); - } - - @SneakyThrows - private Field getRootField() { - Field nodeField = Arrays.stream(tree.getClass().getDeclaredFields()) - .filter(NODE_FIELD) - .findAny() - .orElseThrow(); - nodeField.setAccessible(true); - return nodeField; - } - - @SneakyThrows - private Object getRootObject() { - Field nodeField = Arrays.stream(tree.getClass().getDeclaredFields()) - .filter(NODE_FIELD) - .findAny() - .orElseThrow(); - nodeField.setAccessible(true); - return nodeField.get(tree); - } - - @SneakyThrows - private boolean contains(Object node, int element) { - return findNodeByElement(node, element) != null; - } - - private Object findNodeByElement(Object node, int element) { - if (node == null) { - return null; - } - if (element == getElement(node)) { - return node; - } else if (element < getElement(node)) { - return findNodeByElement(getLeftNode(node), element); - } else if (element > getElement(node)) { - return findNodeByElement(getRightNode(node), element); - } else { - return node; - } - } - - @SneakyThrows - private Field getNodesField(Object node, Predicate option) { - Field field = Arrays.stream(node.getClass().getDeclaredFields()) - .filter(option) - .findAny() - .orElseThrow(); - field.setAccessible(true); - return field; - } - - @SneakyThrows - private int getElement(Object node) { - return (int) getNodesField(node, ELEMENT_FIELD).get(node); - } - - @SneakyThrows - private Object getLeftNode(Object node) { - return getNodesField(node, LEFT_FIELD).get(node); - } - - @SneakyThrows - private Object getRightNode(Object node) { - return getNodesField(node, RIGHT_FIELD).get(node); - } - - @SneakyThrows - private Object newNode(int element) { - Object nodeInstance; - Constructor[] constructors = getInnerClass().getDeclaredConstructors(); - Constructor constructor; - - constructor = constructors[0]; - constructor.setAccessible(true); - if (constructor.getParameters().length == 1) { - nodeInstance = constructor.newInstance(element); - } else { - nodeInstance = constructor.newInstance(); - Field nodeElement = getNodesField(nodeInstance, ELEMENT_FIELD); - nodeElement.set(nodeInstance, element); - } - return nodeInstance; - } - - @SneakyThrows - private void insertElement(int element) { - - Object root = getRootObject(); - - if (root == null) { - getRootField().set(tree, newNode(element)); - } else { - insertToSubtree(root, element); - } - } - - private boolean insertToSubtree(Object node, int element) { - if (element < getElement(node)) { - return insertLeft(node, element); - } else if (element > getElement(node)) { - return insertRight(node, element); - } else { - return false; - } - } - - @SneakyThrows - private boolean insertLeft(Object node, int element) { - if (getLeftNode(node) != null) { - return insertToSubtree(getLeftNode(node), element); - } else { - getNodesField(node, LEFT_FIELD).set(node, newNode(element)); - return true; - } - } - - @SneakyThrows - private boolean insertRight(Object node, int element) { - if (getRightNode(node) != null) { - return insertToSubtree(getRightNode(node), element); - } else { - getNodesField(node, RIGHT_FIELD).set(node, newNode(element)); - return true; - } - } - - @SneakyThrows - private void fillTestTree(Integer... elements) { - tree = new RecursiveBinarySearchTree<>(); - for (Integer e : elements) { - insertElement(e); - } - getInnerSizeField().set(tree, elements.length); - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-9-hash-table/README.md b/2-0-data-structures-and-algorithms/2-2-9-hash-table/README.md deleted file mode 100644 index f1bc7ca37..000000000 --- a/2-0-data-structures-and-algorithms/2-2-9-hash-table/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Hash Table -Learn a Hash Table data structures and build strong skills creating a hash table-based implementation of a Map interface 💪 - -### Objectives (at the end of the training you will be able to...) -* understand the **main idea** behind the **Hash Table** data structure ✅ -* explain why do we need a `hashCode` method and how it speeds up the search ✅ -* implement key-value class `Node` ✅ -* implement a simple `HashTable` based on the array of linked `Node` objects -* realize the limitations of the Hash Table ✅ -* understand why do we need the resizing logic and how does it work ✅ - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-9-hash-table/pom.xml b/2-0-data-structures-and-algorithms/2-2-9-hash-table/pom.xml deleted file mode 100644 index 0453cee6a..000000000 --- a/2-0-data-structures-and-algorithms/2-2-9-hash-table/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 2-2-9-hash-table - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/HashTable.java b/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/HashTable.java deleted file mode 100644 index ade9cea4d..000000000 --- a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/HashTable.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.bobocode.cs; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link HashTable} is a simple Hashtable-based implementation of {@link Map} interface with some additional methods. - * It is based on the array of {@link Node} objects. Both {@link HashTable} and {@link Node} have two type parameters: - * K and V, which represent key and value. - *

- * Elements are stored int the table by their key. A table is basically an array, and fast access is possible due to - * array capabilities. (You can access an array element by its index in O(1) time). In order to find an index for any - * given key, it uses calculateIndex method which is based on the element's hash code. - *

- * If two elements (keys) have the same array index, they form a linked list. That's why class {@link Node} requires - * a reference to the next field. - *

- * Since you don't always know the number of elements in advance, the table can be resized. You can do that manually by - * calling method resizeTable, or it will be done automatically once the table reach resize threshold. - *

- * The initial array size (initial capacity) is 8. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @param key type - * @param value type - * @author Taras Boychuk - */ -public class HashTable implements Map { - - /** - * This method is a critical part of the hast table. The main idea is that having a key, you can calculate its index - * in the array using the hash code. Since the computation is done in constant time (O(1)), it's faster than - * any other kind search. - *

- * It's a function that accepts a key and calculates its index using a hash code. Please note that index cannot be - * equal or greater than array size (table capacity). - *

- * This method is used for all other operations (put, get, remove). - * - * @param key - * @param tableCapacity underlying array size - * @return array index of the given key - */ - public static int calculateIndex(Object key, int tableCapacity) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates a mapping between provided key and value, and returns the old value. If there was no such key, it returns - * null. {@link HashTable} does not support duplicate keys, so if you put the same key it just overrides the value. - *

- * It uses calculateIndex method to find the corresponding array index. Please note, that even different keys can - * produce the same array index. - * - * @param key - * @param value - * @return old value or null - */ - @Override - public V put(K key, V value) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Retrieves a value by the given key. It uses calculateIndex method to find the corresponding array index. - * Then it iterates though all elements that are stored by that index, and uses equals to compare its keys. - * - * @param key - * @return value stored in the table by the given key or null if there is no such key - */ - @Override - public V get(K key) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Checks if the table contains a given key. - * - * @param key - * @return true is there is such key in the table or false otherwise - */ - @Override - public boolean containsKey(K key) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Checks if the table contains a given value. - * - * @param value - * @return true is there is such value in the table or false otherwise - */ - @Override - public boolean containsValue(V value) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Return a number of elements in the table. - * - * @return size - */ - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Checks is the table is empty. - * - * @return true is table size is zero or false otherwise - */ - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Removes an element by its key and returns a removed value. If there is no such key in the table, it returns null. - * - * @param key - * @return removed value or null - */ - @Override - public V remove(K key) { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * It's a special toString method dedicated to help you visualize a hash table. It creates a string that represents - * an underlying array as a table. It has multiples rows. Every row starts with an array index followed by ": ". - * Then it adds every key and value (key=value) that have a corresponding index. Every "next" reference is - * represented as an arrow like this " -> ". - *

- * E.g. imagine a table, where the key is a string username, and the value is the number of points of that user. - * Is this case method toString can return something like this: - *

-     * 0: johnny=439
-     * 1:
-     * 2: madmax=833 -> leon=886
-     * 3:
-     * 4: altea=553
-     * 5:
-     * 6:
-     * 7:
-     * 
- * - * @return - */ - @Override - public String toString() { - throw new ExerciseNotCompletedException(); // todo: - } - - /** - * Creates a new underlying table with a given size and adds all elements to the new table. - *

- * In order to allow a fast access, this hash table needs to have a sufficient capacity. - * (You can imagine a hash table, with a default capacity of 8 that stores hundreds of thousands of elements. - * In that case it's just 8 huge linked lists. That's why we need this method.) - *

- * PLEASE NOTE that such method should not be a part of the public API, but it was made public - * for learning purposes. You can create a table, print it using toString, then resizeTable and print it again. - * It will help you to understand how it works. - * - * @param newCapacity a size of the new underlying array - */ - public void resizeTable(int newCapacity) { - throw new ExerciseNotCompletedException(); // todo: - } -} diff --git a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/Map.java b/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/Map.java deleted file mode 100644 index ede146ae0..000000000 --- a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/main/java/com/bobocode/cs/Map.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.bobocode.cs; - -/** - * A {@link Map} is a simplified interface of so-called dictionary. It maps keys to values and provides an API for data - * access and manipulation. Please note that a map does not support duplicate keys. - *

- * It was added as a simple contact on top of a {@link HashTable} class. - * - * @param key type - * @param value type - * @author Taras Boychuk - */ -public interface Map { - /** - * Creates or updates a mapping for a given key and value. If the key is new, it creates a mapping and return null. - * If the key exists, it updates the value and returns the old value. - * - * @param key - * @param value - * @return an old value or null - */ - V put(K key, V value); - - /** - * Returns the value that is mapped to the given key, or null if there is no such key. - * - * @param key - * @return the value that is mapped to the given key, or null if there is no such key - */ - V get(K key); - - /** - * Returns true if a given key exist or false otherwise. - * - * @param key - * @return true if a given key exist or false otherwise - */ - boolean containsKey(K key); - - /** - * Returns true if a given value exist or false otherwise. - * - * @param value - * @return true if a given value exist or false otherwise - */ - boolean containsValue(V value); - - /** - * Returns the number of entries (key-value mappings). - * - * @return the number of entries - */ - int size(); - - /** - * Returns true if there is no entries or false otherwise. - * - * @return true if there is no entries or false otherwise - */ - boolean isEmpty(); - - /** - * Removes a mapping for a given key, and returns a removed value. If there is no such key, it just returns null. - * - * @param key - * @return a removed value or null - */ - V remove(K key); -} diff --git a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/test/java/com/bobocode/cs/HashTableTest.java b/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/test/java/com/bobocode/cs/HashTableTest.java deleted file mode 100644 index b7355496c..000000000 --- a/2-0-data-structures-and-algorithms/2-2-9-hash-table/src/test/java/com/bobocode/cs/HashTableTest.java +++ /dev/null @@ -1,677 +0,0 @@ -package com.bobocode.cs; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.ClassOrderer.OrderAnnotation; -import org.junit.jupiter.api.*; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.lang.reflect.Modifier.isStatic; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; - -/** - * A Reflection-based step by step test for a {@link HashTable} class. PLEASE NOTE that Reflection API should not be used - * for testing a production code. We use it for learning purposes only! - * - * @author Taras Boychuk - */ -@TestClassOrder(OrderAnnotation.class) -@DisplayName("HashTable Test") -class HashTableTest { - - private HashTable hashTable = new HashTable<>(); - - @Nested - @Order(1) - @DisplayName("1. Node Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class NodeClassTest { - - @Test - @Order(1) - @DisplayName("A nested class Node exists") - void nodeClassExists() { - var nestedClassList = Arrays.stream(HashTable.class.getDeclaredClasses()) - .map(Class::getSimpleName) - .toList(); - - assertThat(nestedClassList).contains("Node"); - } - - @Test - @Order(2) - @DisplayName("Node is a static nested class") - @SneakyThrows - void nodeIsStaticClass() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - - assertTrue(isStatic(nodeClass.getModifiers())); - } - - @Test - @Order(3) - @DisplayName("Node class has two type parameters") - @SneakyThrows - void nodeHasTwoTypeParams() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - var typeParametersList = nodeClass.getTypeParameters(); - - assertThat(typeParametersList).hasSize(2); - } - - @Test - @Order(4) - @DisplayName("Node class has 'key' and 'value' fields") - @SneakyThrows - void nodeHasKeyValuesFields() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - var fieldNames = Arrays.stream(nodeClass.getDeclaredFields()) - .map(Field::getName) - .toList(); - - assertThat(fieldNames).contains("key").contains("value"); - } - - @Test - @Order(5) - @DisplayName("Node class has a field 'next'") - @SneakyThrows - void nodeHasReferenceToNext() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - var fieldNames = Arrays.stream(nodeClass.getDeclaredFields()) - .map(Field::getName) - .toList(); - - assertThat(fieldNames).contains("next"); - } - - @Test - @Order(6) - @DisplayName("Node class has one constructor") - @SneakyThrows - void nodeHasOneConstructor() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - - var constructors = nodeClass.getDeclaredConstructors(); - - assertThat(constructors).hasSize(1); - } - - @Test - @Order(7) - @DisplayName("Node constructor accept key and value") - @SneakyThrows - void nodeConstructorAcceptKeyValue() { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - - var constructor = nodeClass.getDeclaredConstructors()[0]; - - assertThat(constructor.getParameters()).hasSize(2); - assertThat(constructor.getParameters()[0].getName()).isEqualTo("key"); - assertThat(constructor.getParameters()[1].getName()).isEqualTo("value"); - } - } - - @Nested - @Order(2) - @DisplayName("2. HashTable fields Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class HashTableFieldsTest { - - @Test - @Order(1) - @DisplayName("HastTable has a field 'table' which is an array of nodes") - @SneakyThrows - void tableFieldExists() { - var tableField = HashTable.class.getDeclaredField("table"); - var tableType = tableField.getType(); - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - - assertTrue(tableType.isArray()); - assertThat(tableType.getComponentType()).isEqualTo(nodeClass); - } - - @Test - @Order(2) - @DisplayName("HashTable has an integer field 'size'") - @SneakyThrows - void sizeFieldExists() { - var sizeField = HashTable.class.getDeclaredField("size"); - - assertThat(sizeField.getType()).isEqualTo(int.class); - } - } - - @Nested - @Order(3) - @DisplayName("3. HashTable constructors Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class HashTableConstructorsTest { - - @Test - @Order(1) - @SneakyThrows - @DisplayName("A default constructor initializes an array with default size 8") - void defaultConstructor() { - var defaultConstructor = HashTable.class.getConstructor(); - - var hashTable = defaultConstructor.newInstance(); - var table = getInternalTable(hashTable); - - assertThat(table).hasSize(8); - } - - @Test - @Order(2) - @SneakyThrows - @DisplayName("An additional constructor accepts an initial array size") - void constructorWithTableCapacity() { - var constructor = HashTable.class.getConstructor(int.class); - - var hashTable = constructor.newInstance(16); - var table = getInternalTable(hashTable); - - assertThat(table).hasSize(16); - } - - @Test - @Order(3) - @SneakyThrows - @DisplayName("An additional constructor throws exception when argument is negative") - void constructorWithTableCapacityWhenArgumentIsNegative() { - var constructor = HashTable.class.getConstructor(int.class); - - assertThatThrownBy(() -> constructor.newInstance(-2)) - .hasCauseInstanceOf(IllegalArgumentException.class); - } - } - - @Nested - @Order(4) - @DisplayName("4. Hash Function Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class HashFunctionTest { - - @Test - @Order(1) - @DisplayName("calculateIndex returns the same value for the same key") - void calculateIndexReturnTheSameValueWhenKeyIsTheSame() { - var indexSet = Stream.generate(() -> "ASDFDFSD34234234") - .limit(10) - .map(key -> HashTable.calculateIndex(key, 8)) - .collect(Collectors.toSet()); - - assertThat(indexSet).hasSize(1); - } - - @Test - @Order(2) - @DisplayName("calculateIndex returns different values for different keys") - void calculateIndexReturnDifferentValuesWheKeysAreDifferent() { - var arrayCapacity = 8; - var indexSet = Stream.of("A", "Aa", "AaB", "4234", "2234fasdf", "ASDFDFSD34234234", "afsd-fdfd-ae43-5gd3") - .map(str -> HashTable.calculateIndex(str, arrayCapacity)) - .collect(Collectors.toSet()); - - assertThat(indexSet) - .hasSizeGreaterThan(1); - } - - @Test - @Order(3) - @DisplayName("calculateIndex returns values in array bounds") - void calculateIndexReturnIndexInArrayBounds() { - var arrayCapacity = 8; - var keys = Stream.generate(() -> ThreadLocalRandom.current().nextLong()) - .limit(100) - .toList(); - - var indexes = keys.stream() - .map(key -> HashTable.calculateIndex(key, arrayCapacity)) - .toList(); - - assertThat(indexes) - .isNotEmpty() - .allMatch(i -> i >= 0 && i < arrayCapacity); - } - - @Test - @Order(4) - @DisplayName("calculateIndex return non-negative value when hashCode is negative") - void calculateIndexReturnPositiveIndexWhenHashCodeIsNegative() { - var key = Long.MAX_VALUE; - - var index = HashTable.calculateIndex(key, 8); - - assertThat(index).isNotNegative(); - } - } - - @Nested - @Order(5) - @DisplayName("5. HashTable methods Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class HashTableMethodsTest { - - @Test - @SneakyThrows - @Order(1) - @DisplayName("put creates new entry and returns null when the table is empty, should increase the table size") - void putWhenTableIsEmpty() { - var previousValue = hashTable.put("madmax", 833); - - var keyValueExists = checkKeyValueExists("madmax", 833); - - assertNull(previousValue); - assertTrue(keyValueExists); - assertEquals(1, getSize()); - } - - @Test - @Order(2) - @DisplayName("put elements adds entry to the same bucket and increases table size when the hash code is the same") - @SneakyThrows - void putTwoElementsWithTheSameHashCode() { - var table = getInternalTable(hashTable); - var prevValueA = hashTable.put("AaAa", 123); - var prevValueB = hashTable.put("BBBB", 456); - var containsKeyValueA = checkKeyValueExists("AaAa", 123); - var containsKeyValueB = checkKeyValueExists("BBBB", 456); - var bucketIndexA = HashTable.calculateIndex("AaAa", table.length); - var bucketIndexB = HashTable.calculateIndex("BBBB", table.length); - - assertNull(prevValueA); - assertNull(prevValueB); - assertTrue(containsKeyValueA); - assertTrue(containsKeyValueB); - assertThat(bucketIndexA).isEqualTo(bucketIndexB); - assertEquals(2, getSize()); - } - - @Test - @Order(3) - @DisplayName( - "put element updates the value and returns the previous one when key is the same, should not increase table size") - void putElementWithTheSameKey() { - hashTable.put("madmax", 833); - - var previousValue = hashTable.put("madmax", 876); - var containsNewValueByKey = checkKeyValueExists("madmax", 876); - - assertThat(previousValue).isEqualTo(833); - assertTrue(containsNewValueByKey); - assertEquals(1, getSize()); - } - - @Test - @Order(4) - @DisplayName("get returns null when given key does not exists") - void getElementWhenKeyDoesNotExists() { - var foundValue = hashTable.get("xxx"); - - assertNull(foundValue); - } - - @Test - @Order(5) - @DisplayName("get returns a corresponding value by the given key") - void getWhenKeyExists() { - addToTable("madmax", 833); - - var foundValue = hashTable.get("madmax"); - - assertThat(foundValue).isEqualTo(833); - } - - @Test - @Order(6) - @DisplayName("get returns a corresponding value when there are other keys with the same index") - void getWhenOtherKeyHaveTheSameIndex() { - addToTable("madmax", 833); - addToTable("AaAa", 654); - addToTable("BBBB", 721); - - var foundValue = hashTable.get("BBBB"); - - assertThat(foundValue).isEqualTo(721); - } - - @Test - @Order(7) - @DisplayName("containsKey returns true if element exists") - void containsKeyWhenElementExists() { - addToTable("madmax", 833); - - var result = hashTable.containsKey("madmax"); - - assertThat(result).isTrue(); - } - - @Test - @Order(8) - @DisplayName("containsKey returns false if element does not exist") - void containsKeyWhenElementDoesNotExist() { - var result = hashTable.containsKey("madmax"); - - assertThat(result).isFalse(); - } - - @Test - @Order(9) - @DisplayName("containsValue returns true if value exists") - void containsValue() { - addToTable("madmax", 833); - - var result = hashTable.containsValue(833); - - assertThat(result).isTrue(); - } - - @Test - @Order(9) - @DisplayName("containsValue returns false if value does not exist") - void containsValueWhenItDoesNotExist() { - addToTable("madmax", 833); - - var result = hashTable.containsValue(666); - - assertThat(result).isFalse(); - } - - @Test - @Order(10) - @DisplayName("containsValue returns true if the same value appears multiple times") - void containsValueWhenValueAppearsMultipleTimes() { - addToTable("madmax", 833); - addToTable("bobby", 833); - addToTable("altea", 833); - - var result = hashTable.containsValue(833); - - assertThat(result).isTrue(); - } - - @Test - @Order(11) - @SneakyThrows - @DisplayName("size returns the number of entries in the table") - void size() { - setSize(12); - - var size = hashTable.size(); - - assertThat(size).isEqualTo(12); - } - - @Test - @Order(12) - @DisplayName("isEmpty returns false when there are some elements") - void isEmptyWhenTableGetsElements() { - addToTable("madmax", 833); - setSize(1); - - var empty = hashTable.isEmpty(); - - assertFalse(empty); - } - - @Test - @Order(13) - @DisplayName("isEmpty returns true when there is no elements") - void isEmptyWhenThereIsNoElements() { - var empty = hashTable.isEmpty(); - - assertTrue(empty); - } - - @Test - @Order(13) - @DisplayName("remove deletes the entry, decreases table size and returns a value") - void remove() { - addToTable("madmax", 833); - setSize(1); - var result = hashTable.remove("madmax"); - - assertThat(result).isEqualTo(833); - assertFalse(checkKeyValueExists("madmaxx", 833)); - assertEquals(0, getSize()); - } - - @Test - @Order(14) - @DisplayName("remove returns null when key does not exists") - void removeWhenKeyDoesNotExists() { - var result = hashTable.remove("madmax"); - - assertNull(result); - } - - @Test - @Order(15) - @DisplayName("remove deletes the element when it's in the middle of the list and decreases the size of table") - void removeFromTheMiddleOfTheList() { - addToTable("AaAa", 843); - addToTable("BBBB", 434); - addToTable("AaBB", 587); - - var size = 3; - setSize(size); - var removedValue = hashTable.remove("BBBB"); - - assertTrue(checkKeyValueExists("AaAa", 843)); - assertFalse(checkKeyExists("BBBB")); - assertTrue(checkKeyValueExists("AaBB", 587)); - assertThat(removedValue).isEqualTo(434); - assertEquals(size - 1, getSize()); - } - - @Test - @Order(16) - @DisplayName("remove deletes the element when it's in the end of the list and decreases the size of table") - void removeFromTheEndOfTheList() { - addToTable("AaAa", 843); - addToTable("BBBB", 434); - addToTable("AaBB", 587); - var size = 3; - setSize(size); - - var removedValue = hashTable.remove("AaBB"); - - assertTrue(checkKeyValueExists("AaAa", 843)); - assertTrue(checkKeyValueExists("BBBB", 434)); - assertFalse(checkKeyExists("AaBB")); - assertThat(removedValue).isEqualTo(587); - assertEquals(2, getSize()); - } - } - - @Nested - @Order(6) - @DisplayName("6. Helper methods Test") - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class HashTableHelperMethodsTest { - - @Test - @Order(1) - @DisplayName("resizeTable creates a new array and put there all elements") - void resizeTable() { - addToTable("madmax", 833); - addToTable("altea", 553); - addToTable("AaAa", 123); - addToTable("BBBB", 456); - - hashTable.resizeTable(16); - - assertThat(getInternalTable(hashTable)).hasSize(16); - assertTrue(checkKeyValueExists("madmax", 833)); - assertTrue(checkKeyValueExists("altea", 553)); - assertTrue(checkKeyValueExists("AaAa", 123)); - assertTrue(checkKeyValueExists("BBBB", 456)); - } - - @Test - @DisplayName("toString returns a string that represents an underlying table") - void toStringTest() { - addToTable("madmax", 833); - addToTable("altea", 553); - addToTable("johnny", 439); - addToTable("leon", 886); - var table = getInternalTable(hashTable); - var expectedString = tableToString(table); - - String tableStr = hashTable.toString(); - - assertThat(tableStr).isEqualTo(expectedString); - } - - } - - // Util methods - @SneakyThrows - private Object[] getInternalTable(HashTable hashTable) { - var tableField = HashTable.class.getDeclaredField("table"); - tableField.setAccessible(true); - return (Object[]) tableField.get(hashTable); - } - - private void addToTable(String key, Integer value) { - var table = getInternalTable(hashTable); - var index = HashTable.calculateIndex(key, table.length); - var newNode = createNewNode(key, value); - if (table[index] == null) { - table[index] = newNode; - } else { - var current = new NodeProxy(table[index]); - while (current.next() != null && !current.key().equals(key)) { - current = current.next(); - } - if (current.key().equals(key)) { - current.setValue(value); - } else { - current.setNext(newNode); - } - } - } - - private NodeProxy getNodeByKey(Object key) { - var table = getInternalTable(hashTable); - for (var head : table) { - if (head != null) { - var current = new NodeProxy(head); - while (current != null) { - if (current.key().equals(key)) { - return current; - } - current = current.next(); - } - } - } - return null; - } - - private boolean checkKeyValueExists(Object key, Object value) { - var node = getNodeByKey(key); - return node != null && node.value().equals(value); - } - - private boolean checkKeyExists(Object key) { - var node = getNodeByKey(key); - return node != null; - } - - @SneakyThrows - private void setSize(int size) { - var sizeField = HashTable.class.getDeclaredField("size"); - sizeField.setAccessible(true); - sizeField.set(hashTable, size); - } - - @SneakyThrows - private int getSize() { - var sizeField = HashTable.class.getDeclaredField("size"); - sizeField.setAccessible(true); - return sizeField.getInt(hashTable); - } - - private String tableToString(Object[] table) { - StringBuilder result = new StringBuilder(); - var n = table.length; - for (int i = 0; i < n; i++) { - result.append(i).append(": "); - if (table[i] != null) { - var current = new NodeProxy(table[i]); - while (current.next() != null) { - result.append(current.key()).append("=").append(current.value()).append(" -> "); - current = current.next(); - } - result.append(current.key()).append("=").append(current.value()); - } - result.append("\n"); - } - return result.toString(); - } - - @SneakyThrows - private Object createNewNode(String key, Integer value) { - var nodeClass = Class.forName("com.bobocode.cs.HashTable$Node"); - var constructor = nodeClass.getConstructor(Object.class, Object.class); - return constructor.newInstance(key, value); - } - - static class NodeProxy { - - Class targetClass; - Field keyField; - Field valueField; - Field nextField; - Object target; - - @SneakyThrows - public NodeProxy(Object target) { - Objects.requireNonNull(target); - this.targetClass = Class.forName("com.bobocode.cs.HashTable$Node"); - this.target = target; - this.keyField = targetClass.getDeclaredField("key"); - this.keyField.setAccessible(true); - this.valueField = targetClass.getDeclaredField("value"); - this.valueField.setAccessible(true); - this.nextField = targetClass.getDeclaredField("next"); - this.nextField.setAccessible(true); - } - - @SneakyThrows - public Object key() { - return keyField.get(target); - } - - @SneakyThrows - public Object value() { - return valueField.get(target); - } - - @SneakyThrows - public NodeProxy next() { - return Optional.ofNullable(nextField.get(target)) - .map(NodeProxy::new) - .orElse(null); - } - - @SneakyThrows - public void setValue(Object value) { - valueField.set(target, value); - } - - @SneakyThrows - public void setNext(Object newNode) { - nextField.set(target, newNode); - } - } -} \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/README.md b/2-0-data-structures-and-algorithms/README.md deleted file mode 100644 index f00ce989c..000000000 --- a/2-0-data-structures-and-algorithms/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Data Structures & Angorithms -Learn Data Structures & Algorithms and build strong related skills needed for enterprise Java development 💪 \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/pom.xml b/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/pom.xml deleted file mode 100644 index 87de65e23..000000000 --- a/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 2-0-data-structures-and-algorithms - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - data-structures-and-algorithms-util - - - \ No newline at end of file diff --git a/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/src/main/java/com/bobocode/cs/List.java b/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/src/main/java/com/bobocode/cs/List.java deleted file mode 100644 index dfa0a7cd8..000000000 --- a/2-0-data-structures-and-algorithms/data-structures-and-algorithms-util/src/main/java/com/bobocode/cs/List.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.bobocode.cs; - - -public interface List { - void add(T element); - - void add(int index, T element); - - void set(int index, T element); - - T get(int index); - - T getFirst(); - - T getLast(); - - T remove(int index); - - boolean contains(T element); - - boolean isEmpty(); - - int size(); - - void clear(); -} diff --git a/2-0-data-structures-and-algorithms/pom.xml b/2-0-data-structures-and-algorithms/pom.xml deleted file mode 100644 index a08d31d22..000000000 --- a/2-0-data-structures-and-algorithms/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - pom - - 2-2-1-node - 2-2-2-stack - 2-2-3-linked-queue - 2-2-4-linked-list - 2-2-5-array-list - 2-2-6-binary-search-tree - 2-2-9-hash-table - data-structures-and-algorithms-util - - - - com.bobocode - java-fundamentals-exercises - 1.0-SNAPSHOT - - 2-0-data-structures-and-algorithms - - - - - com.bobocode - java-fundamentals-util - 1.0-SNAPSHOT - compile - - - - \ No newline at end of file diff --git a/3-0-java-core/3-6-1-file-reader/README.MD b/3-0-java-core/3-6-1-file-reader/README.MD deleted file mode 100644 index 5d6989629..000000000 --- a/3-0-java-core/3-6-1-file-reader/README.MD +++ /dev/null @@ -1,17 +0,0 @@ -# File Reader -Improve your Java SE skills by implementing a logic that reads file content using Stream API 💪 - -### Pre-conditions ❗ -You're supposed to know the basics of Stream API and how to work with files in Java - -### Objectives -* **find a text file** in the classpath ✅ -* **open a** `Stream` of file lines ✅ -* **collect** file content into a single `String` ✅ -* **deal with exceptions** when accessing the file ✅ - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/3-0-java-core/3-6-1-file-reader/pom.xml b/3-0-java-core/3-6-1-file-reader/pom.xml deleted file mode 100644 index 67b2f5f5b..000000000 --- a/3-0-java-core/3-6-1-file-reader/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 3-0-java-core - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 3-6-1-file-reader - - - \ No newline at end of file diff --git a/3-0-java-core/3-6-1-file-reader/src/main/java/com/bobocode/se/FileReaders.java b/3-0-java-core/3-6-1-file-reader/src/main/java/com/bobocode/se/FileReaders.java deleted file mode 100644 index 6370a3638..000000000 --- a/3-0-java-core/3-6-1-file-reader/src/main/java/com/bobocode/se/FileReaders.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.bobocode.se; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link FileReaders} provides an API that allow to read whole file into a {@link String} by file name. - */ -public class FileReaders { - - /** - * Returns a {@link String} that contains whole text from the file specified by name. - * - * @param fileName a name of a text file - * @return string that holds whole file content - */ - public static String readWholeFile(String fileName) { - throw new ExerciseNotCompletedException(); //todo - } -} diff --git a/3-0-java-core/3-6-1-file-reader/src/test/java/com/bobocode/se/FileReadersTest.java b/3-0-java-core/3-6-1-file-reader/src/test/java/com/bobocode/se/FileReadersTest.java deleted file mode 100644 index 1c24b9d2d..000000000 --- a/3-0-java-core/3-6-1-file-reader/src/test/java/com/bobocode/se/FileReadersTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.bobocode.se; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class FileReadersTest { - - @Test - void testReadWholeFileOnEmptyFile() { - String fileContent = FileReaders.readWholeFile("empty.txt"); - - assertEquals("", fileContent); - - } - - @Test - void testReadWholeFileOnFileWithEmptyLines() { - String fileContent = FileReaders.readWholeFile("lines.txt"); - - assertEquals("Hey!\n" + - "\n" + - "What's up?\n" + - "\n" + - "Hi!", fileContent); - } - - @Test - void testReadWholeFile() { - String fileContent = FileReaders.readWholeFile("simple.txt"); - - assertEquals("Hello!\n" + "It's a test file.", fileContent); - } -} diff --git a/3-0-java-core/3-6-1-file-reader/src/test/resources/empty.txt b/3-0-java-core/3-6-1-file-reader/src/test/resources/empty.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/3-0-java-core/3-6-1-file-reader/src/test/resources/lines.txt b/3-0-java-core/3-6-1-file-reader/src/test/resources/lines.txt deleted file mode 100644 index 7c294a97f..000000000 --- a/3-0-java-core/3-6-1-file-reader/src/test/resources/lines.txt +++ /dev/null @@ -1,5 +0,0 @@ -Hey! - -What's up? - -Hi! \ No newline at end of file diff --git a/3-0-java-core/3-6-1-file-reader/src/test/resources/simple.txt b/3-0-java-core/3-6-1-file-reader/src/test/resources/simple.txt deleted file mode 100644 index ac906f0b9..000000000 --- a/3-0-java-core/3-6-1-file-reader/src/test/resources/simple.txt +++ /dev/null @@ -1,2 +0,0 @@ -Hello! -It's a test file. \ No newline at end of file diff --git a/3-0-java-core/3-6-2-file-stats/README.MD b/3-0-java-core/3-6-2-file-stats/README.MD deleted file mode 100644 index 4cfa45009..000000000 --- a/3-0-java-core/3-6-2-file-stats/README.MD +++ /dev/null @@ -1,20 +0,0 @@ -# Files Stats -Improve your Stream API skills calculating character statistic using a text file 💪 - -### Pre-conditions ❗ -You're supposed to know how to work with text files and be able to write Java code - -### Objectives - -* **find a text file** in the classpath ✅ -* **open a** `Stream` of file lines ✅ -* **transform** a stream of lines into a stream of characters -* **group** characters by value and calculate needed stats ✅ -* **deal with exceptions** when accessing the file ✅ - ---- - -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -
\ No newline at end of file diff --git a/3-0-java-core/3-6-2-file-stats/pom.xml b/3-0-java-core/3-6-2-file-stats/pom.xml deleted file mode 100644 index 448ac3179..000000000 --- a/3-0-java-core/3-6-2-file-stats/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 3-0-java-core - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 3-6-2-file-stats - - - \ No newline at end of file diff --git a/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStats.java b/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStats.java deleted file mode 100644 index 56b4aa596..000000000 --- a/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStats.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.bobocode.se; - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link FileStats} provides an API that allow to get character statistic based on text file. All whitespace characters - * are ignored. - */ -public class FileStats { - /** - * Creates a new immutable {@link FileStats} objects using data from text file received as a parameter. - * - * @param fileName input text file name - * @return new FileStats object created from text file - */ - public static FileStats from(String fileName) { - throw new ExerciseNotCompletedException(); //todo - } - - /** - * Returns a number of occurrences of the particular character. - * - * @param character a specific character - * @return a number that shows how many times this character appeared in a text file - */ - public int getCharCount(char character) { - throw new ExerciseNotCompletedException(); //todo - } - - /** - * Returns a character that appeared most often in the text. - * - * @return the most frequently appeared character - */ - public char getMostPopularCharacter() { - throw new ExerciseNotCompletedException(); //todo - } - - /** - * Returns {@code true} if this character has appeared in the text, and {@code false} otherwise - * - * @param character a specific character to check - * @return {@code true} if this character has appeared in the text, and {@code false} otherwise - */ - public boolean containsCharacter(char character) { - throw new ExerciseNotCompletedException(); //todo - } -} diff --git a/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStatsException.java b/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStatsException.java deleted file mode 100644 index d2f03c253..000000000 --- a/3-0-java-core/3-6-2-file-stats/src/main/java/com/bobocode/se/FileStatsException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.bobocode.se; - -public class FileStatsException extends RuntimeException{ - public FileStatsException(String message) { - super(message); - } - - public FileStatsException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/3-0-java-core/3-6-2-file-stats/src/test/java/com/bobocode/se/FileStatsTest.java b/3-0-java-core/3-6-2-file-stats/src/test/java/com/bobocode/se/FileStatsTest.java deleted file mode 100644 index b1eb222af..000000000 --- a/3-0-java-core/3-6-2-file-stats/src/test/java/com/bobocode/se/FileStatsTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.bobocode.se; - -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import static org.assertj.core.api.Assertions.*; - -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class FileStatsTest { - - @Test - @Order(1) - void createFileStatsFromExistingFile() { - FileStats fileStats = FileStats.from("sotl.txt"); - } - - @Test - @Order(2) - void createFileStatsFromNonExistingFile() { - assertThatThrownBy(() -> FileStats.from("blahblah.txt")).isInstanceOf(FileStatsException.class); - } - - @Test - @Order(3) - void getCharCount() { - FileStats lambdaArticleFileStats = FileStats.from("sotl.txt"); - FileStats springCloudArticleFileStats = FileStats.from("scosb.txt"); - - int aCharCountInLambdaArticle = lambdaArticleFileStats.getCharCount('a'); - int bCharCountInSpringArticle = springCloudArticleFileStats.getCharCount('b'); - - assertThat(aCharCountInLambdaArticle).isEqualTo(2345); - assertThat(bCharCountInSpringArticle).isEqualTo(4); - } - - @Test - @Order(4) - void getMostPopularCharacter() { - FileStats lambdaArticleFileStats = FileStats.from("sotl.txt"); - FileStats springCloudArticleFileStats = FileStats.from("scosb.txt"); - - char mostPopularCharacterInLambdaArticle = lambdaArticleFileStats.getMostPopularCharacter(); - char mostPopularCharacterInSpringArticle = springCloudArticleFileStats.getMostPopularCharacter(); - - System.out.println(mostPopularCharacterInSpringArticle); - - assertThat(mostPopularCharacterInLambdaArticle).isEqualTo('e'); - assertThat(mostPopularCharacterInSpringArticle).isEqualTo('e'); - } - - @Test - @Order(5) - void containsCharacter() { - FileStats lambdaArticleFileStats = FileStats.from("sotl.txt"); - FileStats springCloudArticleFileStats = FileStats.from("scosb.txt"); - - boolean lambdaArticleContainsExistingCharacter = lambdaArticleFileStats.containsCharacter('a'); - boolean lambdaArticleContainsWhitespace = lambdaArticleFileStats.containsCharacter(' '); - boolean springArticleContainsExistingCharacter = springCloudArticleFileStats.containsCharacter('b'); - boolean springArticleContainsWhitespace = springCloudArticleFileStats.containsCharacter(' '); - - assertThat(lambdaArticleContainsExistingCharacter).isTrue(); - assertThat(lambdaArticleContainsWhitespace).isFalse(); - assertThat(springArticleContainsExistingCharacter).isTrue(); - assertThat(springArticleContainsWhitespace).isFalse(); - } -} \ No newline at end of file diff --git a/3-0-java-core/3-6-2-file-stats/src/test/resources/scosb.txt b/3-0-java-core/3-6-2-file-stats/src/test/resources/scosb.txt deleted file mode 100644 index 44e38c020..000000000 --- a/3-0-java-core/3-6-2-file-stats/src/test/resources/scosb.txt +++ /dev/null @@ -1,3 +0,0 @@ -We’re pleased to announce that the 2.0.1 release of Spring Cloud Open Service Broker is now available. This release resolves a few issues that were raised since the 2.0.0 release. Thank you to the community for your interest and feedback! - -Spring Cloud Open Service Broker is a framework for building Spring Boot applications that implement the Open Service Broker API. The Open Service Broker API project allows developers to deliver services to applications running within cloud native platforms such as Cloud Foundry, Kubernetes, and OpenShift. \ No newline at end of file diff --git a/3-0-java-core/3-6-2-file-stats/src/test/resources/sotl.txt b/3-0-java-core/3-6-2-file-stats/src/test/resources/sotl.txt deleted file mode 100644 index c00c796f2..000000000 --- a/3-0-java-core/3-6-2-file-stats/src/test/resources/sotl.txt +++ /dev/null @@ -1,411 +0,0 @@ -State of the Lambda -September 2013 -Java SE 8 Edition -This is an informal overview of the enhancements to the Java programming language specified by JSR 335 and implemented in the OpenJDK Lambda Project. It refines the previous iteration posted in December 2011. A formal description of some of the language changes may be found in the Early Draft Specification for the JSR; an OpenJDK Developer Preview is also available. Additional historical design documents can be found at the OpenJDK project page. There is also a companion document, State of the Lambda, Libraries Edition, describing the library enhancements added as part of JSR 335. - -The high-level goal of Project Lambda is to enable programming patterns that require modeling code as data to be convenient and idiomatic in Java. The principal new language features include: - -Lambda expressions (informally, "closures" or "anonymous methods") -Method and constructor references -Expanded target typing and type inference -Default and static methods in interfaces -These are described and illustrated below. - -1. Background -Java is, primarily, an object-oriented programming language. In both object-oriented and functional languages, basic values can dynamically encapsulate program behavior: object-oriented languages have objects with methods, and functional languages have functions. This similarity may not be obvious, however, because Java objects tend to be relatively heavyweight: instantiations of separately-declared classes wrapping a handful of fields and many methods. - -Yet it is common for some objects to essentially encode nothing more than a function. In a typical use case, a Java API defines an interface, sometimes described as a "callback interface," expecting the user to provide an instance of the interface when invoking the API. For example: - -public interface ActionListener { - void actionPerformed(ActionEvent e); -} -Rather than declaring a class that implements ActionListener for the sole purpose of allocating it once at an invocation site, a user typically instantiates the implementing class inline, anonymously: - -button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ui.dazzle(e.getModifiers()); - } -}); -Many useful libraries rely on this pattern. It is particularly important for parallel APIs, in which the code to execute must be expressed independently of the thread in which it will run. The parallel-programming domain is of special interest, because as Moore's Law continues to give us more cores but not faster cores, serial APIs are limited to a shrinking fraction of available processing power. - -Given the increasing relevance of callbacks and other functional-style idioms, it is important that modeling code as data in Java be as lightweight as possible. In this respect, anonymous inner classes are imperfect for a number of reasons, primarily: - -Bulky syntax -Confusion surrounding the meaning of names and this -Inflexible class-loading and instance-creation semantics -Inability to capture non-final local variables -Inability to abstract over control flow -This project addresses many of these issues. It eliminates (1) and (2) by introducing new, much more concise expression forms with local scoping rules, sidesteps (3) by defining the semantics of the new expressions in a more flexible, optimization-friendly manner, and ameliorates (4) by allowing the compiler to infer finality (allowing capture of effectively final local variables). - -However, it is not a goal of this project to address all the problems of inner classes. Neither arbitrary capture of mutable variables (4) nor nonlocal control flow (5) are within this project's scope (though such features may be revisited in a future iteration of the language.) - -2. Functional interfaces -The anonymous inner class approach, despite its limitations, has the nice property of fitting very cleanly into Java's type system: a function value with an interface type. This is convenient for a number of reasons: interfaces are already an intrinsic part of the type system; they naturally have a runtime representation; and they carry with them informal contracts expressed by Javadoc comments, such as an assertion that an operation is commutative. - -The interface ActionListener, used above, has just one method. Many common callback interfaces have this property, such as Runnable and Comparator. We'll give all interfaces that have just one method a name: functional interfaces. (These were previously called SAM Types, which stood for "Single Abstract Method".) - -Nothing special needs to be done to declare an interface as functional; the compiler identifies it as such based on its structure. (This identification process is a little more than just counting method declarations; an interface might redundantly declare a method that is automatically provided by the class Object, such as toString(), or might declare static or default methods, none of which count against the one-method limit.) However, API authors may additionally capture the design intent that an interface be functional (as opposed to accidentally having only one method) with the @FunctionalInterface annotation, in which case the compiler will validate that the interface meets the structural requirements to be a functional interface. - -An alternative (or complementary) approach to function types, suggested by some early proposals, would have been to introduce a new, structural function type, sometimes called arrow types. A type like "function from a String and an Object to an int" might be expressed as (String,Object)->int. This idea was considered and rejected, at least for now, due to several disadvantages: - -It would add complexity to the type system and further mix structural and nominal types (Java is almost entirely nominally typed). -It would lead to a divergence of library styles -- some libraries would continue to use callback interfaces, while others would use structural function types. -The syntax could be unwieldy, especially when checked exceptions were included. -It is unlikely that there would be a runtime representation for each distinct function type, meaning developers would be further exposed to and limited by erasure. For example, it would not be possible (perhaps surprisingly) to overload methods m(T->U) and m(X->Y). -So, we have instead followed the path of "use what you know" -- since existing libraries use functional interfaces extensively, we codify and leverage this pattern. This enables existing libraries to be used with lambda expressions. - -To illustrate, here is a sampling of some of the functional interfaces already in Java SE 7 that are well-suited for being used with the new language features; the examples that follow illustrate the use of a few of them. - -java.lang.Runnable -java.util.concurrent.Callable -java.security.PrivilegedAction -java.util.Comparator -java.io.FileFilter -java.beans.PropertyChangeListener -In addition, Java SE 8 adds a new package, java.util.function, which contains functional interfaces that are expected to be commonly used, such as: - -Predicate -- a boolean-valued property of an object -Consumer -- an action to be performed on an object -Function -- a function transforming a T to a R -Supplier -- provide an instance of a T (such as a factory) -UnaryOperator -- a function from T to T -BinaryOperator -- a function from (T, T) to T -In addition to these basic "shapes", there are also primitive specializations such as IntSupplier or LongBinaryOperator. (Rather than provide the full complement of primitive specializations, we provide only specializations for int, long, and double; the other primitive types can be accomodated through conversions.) Similarly, there are some specializations for multiple arities, such as BiFunction, which represents a function from (T,U) to R. - -3. Lambda expressions -The biggest pain point for anonymous classes is bulkiness. They have what we might call a "vertical problem": the ActionListener instance from section 1 uses five lines of source code to encapsulate a single aspect of behavior. - -Lambda expressions are anonymous methods, aimed at addressing the "vertical problem" by replacing the machinery of anonymous inner classes with a lighter-weight mechanism. - -Here are some examples of lambda expressions: - -(int x, int y) -> x + y - -() -> 42 - -(String s) -> { System.out.println(s); } -The first expression takes two integer arguments, named x and y, and returns their sum. The second takes no arguments and returns the integer 42. The third takes a string and prints it to the console, returning nothing. - -The general syntax consists of an argument list, the arrow token ->, and a body. The body can either be a single expression, or a statement block. In the expression form, the body is simply evaluated and returned. In the block form, the body is evaluated like a method body -- a return statement returns control to the caller of the anonymous method; break and continue are illegal at the top level, but are of course permitted within loops; and if the body produces a result, every control path must return something or throw an exception. - -The syntax is optimized for the common case in which a lambda expression is quite small, as illustrated above. For example, the expression-body form eliminates the need for a return keyword, which could otherwise represent a substantial syntactic overhead relative to the size of the expression. - -It is also expected that lambda expressions will frequently appear in nested contexts, such as the argument to a method invocation or the result of another lambda expression. To minimize noise in these cases, unnecessary delimiters are avoided. However, for situations in which it is useful to set the entire expression apart, it can be surrounded with parentheses, just like any other expression. - -Here are some examples of lambda expressions appearing in statements: - -FileFilter java = (File f) -> f.getName().endsWith(".java"); - -String user = doPrivileged(() -> System.getProperty("user.name")); - -new Thread(() -> { - connectToService(); - sendNotification(); -}).start(); -4. Target typing -Note that the name of a functional interface is not part of the lambda expression syntax. So what kind of object does a lambda expression represent? Its type is inferred from the surrounding context. For example, the following lambda expression is an ActionListener: - -ActionListener l = (ActionEvent e) -> ui.dazzle(e.getModifiers()); -An implication of this approach is that the same lambda expression can have different types in different contexts: - -Callable c = () -> "done"; - -PrivilegedAction a = () -> "done"; -In the first case, the lambda expression () -> "done" represents an instance of Callable. In the second case, the same expression represents an instance of PrivilegedAction. - -The compiler is responsible for inferring the type of each lambda expression. It uses the type expected in the context in which the expression appears; this type is called the target type. A lambda expression can only appear in a context whose target type is a functional interface. - -Of course, no lambda expression will be compatible with every possible target type. The compiler checks that the types used by the lambda expression are consistent with the target type's method signature. That is, a lambda expression can be assigned to a target type T if all of the following conditions hold: - -T is a functional interface type -The lambda expression has the same number of parameters as T's method, and those parameters' types are the same -Each expression returned by the lambda body is compatible with T's method's return type -Each exception thrown by the lambda body is allowed by T's method's throws clause -Since a functional interface target type already "knows" what types the lambda expression's formal parameters should have, it is often unnecessary to repeat them. The use of target typing enables the lambda parameters' types to be inferred: - -Comparator c = (s1, s2) -> s1.compareToIgnoreCase(s2); -Here, the compiler infers that the type of s1 and s2 is String. In addition, when there is just one parameter whose type is inferred (a very common case), the parentheses surrounding a single parameter name are optional: - -FileFilter java = f -> f.getName().endsWith(".java"); - -button.addActionListener(e -> ui.dazzle(e.getModifiers())); -These enhancements further a desirable design goal: "Don't turn a vertical problem into a horizontal problem." We want the reader of the code to have to wade through as little syntax as possible before arriving at the "meat" of the lambda expression. - -Lambda expressions are not the first Java expressions to have context-dependent types: generic method invocations and "diamond" constructor invocations, for example, are similarly type-checked based on an assignment's target type. - -List ls = Collections.emptyList(); -List li = Collections.emptyList(); - -Map m1 = new HashMap<>(); -Map m2 = new HashMap<>(); -5. Contexts for target typing -We stated earlier that lambda expressions can only appear in contexts that have target types. The following contexts have target types: - -Variable declarations -Assignments -Return statements -Array initializers -Method or constructor arguments -Lambda expression bodies -Conditional expressions (?:) -Cast expressions -In the first three cases, the target type is simply the type being assigned to or returned. - -Comparator c; -c = (String s1, String s2) -> s1.compareToIgnoreCase(s2); - -public Runnable toDoLater() { - return () -> { - System.out.println("later"); - }; -} -Array initializer contexts are like assignments, except that the "variable" is an array component and its type is derived from the array's type. - -filterFiles(new FileFilter[] { - f -> f.exists(), f -> f.canRead(), f -> f.getName().startsWith("q") - }); -In the method argument case, things are more complicated: target type determination interacts with two other language features, overload resolution and type argument inference. - -Overload resolution involves finding the best method declaration for a particular method invocation. Since different declarations have different signatures, this can impact the target type of a lambda expression used as an argument. The compiler will use what it knows about the lambda expression to make this choice. If a lambda expression is explicitly typed (specifies the types of its parameters), the compiler will know not only the parameter types but also the type of all return expressions in its body. If the lambda is implicitly typed (inferred parameter types), overload resolution will ignore the lambda body and only use the number of lambda parameters. - -If the choice of a best method declaration is ambiguous, casts or explicit lambdas can provide additional type information for the compiler to disambiguate. If the return type targeted by a lambda expression depends on type argument inference, then the lambda body may provide information to the compiler to help infer the type arguments. - -List ps = ... -String names = ps.stream().map(p -> p.getName()); -Here, ps is a List, so ps.stream() is a Stream. The map() method is generic in R, where the parameter of map() is a Function, where T is the stream element type. (T is known to be Person at this point.) Once the overload is selected and the lambda's target type is known, we need to infer R; we do this by type-checking the lambda body, and discovering that its return type is String, and hence R is String, and therefore the map() expression has a type of Stream. Most of the time, the compiler just figures this all out, but if it gets stuck, we can provide additional type information via an explicit lambda (give the argument p an explicit type), casting the lambda to an explicit target type such as Function, or providing an explicit type witness for the generic parameter R (.map(p -> p.getName())). - -Lambda expressions themselves provide target types for their bodies, in this case by deriving that type from the outer target type. This makes it convenient to write functions that return other functions: - -Supplier c = () -> () -> { System.out.println("hi"); }; -Similarly, conditional expressions can "pass down" a target type from the surrounding context: - -Callable c = flag ? (() -> 23) : (() -> 42); -Finally, cast expressions provide a mechanism to explicitly provide a lambda expression's type if none can be conveniently inferred from context: - -// Illegal: Object o = () -> { System.out.println("hi"); }; -Object o = (Runnable) () -> { System.out.println("hi"); }; -Casts are also useful to help resolve ambiguity when a method declaration is overloaded with unrelated functional interface types. - -The expanded role of target typing in the compiler is not limited to lambda expressions: generic method invocations and "diamond" constructor invocations can also take advantage of target types wherever they are available. The following declarations are illegal in Java SE 7 but valid in Java SE 8: - -List ls = - Collections.checkedList(new ArrayList<>(), String.class); - -Set si = flag ? Collections.singleton(23) - : Collections.emptySet(); -6. Lexical scoping -Determining the meaning of names (and this) in inner classes is significantly more difficult and error-prone than when classes are limited to the top level. Inherited members -- including methods of class Object -- can accidentally shadow outer declarations, and unqualified references to this always refer to the inner class itself. - -Lambda expressions are much simpler: they do not inherit any names from a supertype, nor do they introduce a new level of scoping. Instead, they are lexically scoped, meaning names in the body are interpreted just as they are in the enclosing environment (with the addition of new names for the lambda expression's formal parameters). As a natural extension, the this keyword and references to its members have the same meaning as they would immediately outside the lambda expression. - -To illustrate, the following program prints "Hello, world!" twice to the console: - -public class Hello { - Runnable r1 = () -> { System.out.println(this); } - Runnable r2 = () -> { System.out.println(toString()); } - - public String toString() { return "Hello, world!"; } - - public static void main(String... args) { - new Hello().r1.run(); - new Hello().r2.run(); - } -} -The equivalent using anonymous inner classes would instead, perhaps to the programmer's surprise, print something like Hello$1@5b89a773 and Hello$2@537a7706. - -Consistent with the lexical-scoping approach, and following the pattern set by other local parameterized constructs like for loops and catch clauses, the parameters of a lambda expression must not shadow any local variables in the enclosing context. - -7. Variable capture -The compiler check for references to local variables of enclosing contexts in inner classes (captured variables) is quite restrictive in Java SE 7: an error occurs if the captured variable is not declared final. We relax this restriction -- for both lambda expressions and inner classes -- by also allowing the capture of effectively final local variables. - -Informally, a local variable is effectively final if its initial value is never changed -- in other words, declaring it final would not cause a compilation failure. - -Callable helloCallable(String name) { - String hello = "Hello"; - return () -> (hello + ", " + name); -} -References to this -- including implicit references through unqualified field references or method invocations -- are, essentially, references to a final local variable. Lambda bodies that contain such references capture the appropriate instance of this. In other cases, no reference to this is retained by the object. - -This has a beneficial implication for memory management: while inner class instances always hold a strong reference to their enclosing instance, lambdas that do not capture members from the enclosing instance do not hold a reference to it. This characteristic of inner class instances can often be a source of memory leaks. - -While we relax the syntactic restrictions on captured values, we still prohibit capture of mutable local variables. The reason is that idioms like this: - -int sum = 0; -list.forEach(e -> { sum += e.size(); }); // ERROR -are fundamentally serial; it is quite difficult to write lambda bodies like this that do not have race conditions. Unless we are willing to enforce -- preferably at compile time -- that such a function cannot escape its capturing thread, this feature may well cause more trouble than it solves. Lambda expressions close over values, not variables. - -Another reason to not support capture of mutable variables is that there's a better way to address accumulation problems without mutation, and instead treat this problem as a reduction. The java.util.stream package provides both general and specialized (such as sum, min, and max) reductions on collections and other data structures. For example, instead of using forEach and mutation, we could do a reduction which is safe both sequentially or in parallel: - -int sum = list.stream() - .mapToInt(e -> e.size()) - .sum(); -The sum() method is provided for convenience, but is equivalent to the more general form of reduction: - -int sum = list.stream() - .mapToInt(e -> e.size()) - .reduce(0, (x,y) -> x+y); -Reduction takes a base value (in case the input is empty) and an operator (here, addition), and computes the following expression: - -0 + list[0] + list[1] + list[2] + ... -Reduction can be done with other operations as well, such as minimum, maximum, product, etc, and if the operator is associative, is easily and safely parallelized. So, rather than supporting an idiom that is fundamentally sequential and prone to data races (mutable accumulators), we instead choose to provide library support to express accumulations in a more parallelizable and less error-prone way. - -8. Method references -Lambda expressions allow us to define an anonymous method and treat it as an instance of a functional interface. It is often desirable to do the same with an existing method. - -Method references are expressions which have the same treatment as lambda expressions (i.e., they require a target type and encode functional interface instances), but instead of providing a method body, they refer an existing method by name. - -For example, consider a Person class that can be sorted by name or by age. - -class Person { - private final String name; - private final int age; - - public int getAge() { return age; } - public String getName() { return name; } - ... -} - -Person[] people = ... -Comparator byName = Comparator.comparing(p -> p.getName()); -Arrays.sort(people, byName); -We can rewrite this to use a method reference to Person.getName() instead: - -Comparator byName = Comparator.comparing(Person::getName); -Here, the expression Person::getName can be considered shorthand for a lambda expression which simply invokes the named method with its arguments, and returns the result. While the method reference may not (in this case) be any more syntactically compact, it is clearer -- the method that we want to call has a name, and so we can refer to it directly by name. - -Because the functional interface method's parameter types act as arguments in an implicit method invocation, the referenced method signature is allowed to manipulate the parameters -- via widening, boxing, grouping as a variable-arity array, etc. -- just like a method invocation. - -Consumer b1 = System::exit; // void exit(int status) -Consumer b2 = Arrays::sort; // void sort(Object[] a) -Consumer b3 = MyProgram::main; // void main(String... args) -Runnable r = MyProgram::main; // void main(String... args) -9. Kinds of method references -There are several different kinds of method references, each with slightly different syntax: - -A static method (ClassName::methName) -An instance method of a particular object (instanceRef::methName) -A super method of a particular object (super::methName) -An instance method of an arbitrary object of a particular type (ClassName::methName) -A class constructor reference (ClassName::new) -An array constructor reference (TypeName[]::new) -For a static method reference, the class to which the method belongs precedes the :: delimiter, such as in Integer::sum. - -For a reference to an instance method of a particular object, an expression evaluating to an object reference precedes the delimiter: - -Set knownNames = ... -Predicate isKnown = knownNames::contains; -Here, the implicit lambda expression would capture the String object referred to by knownNames, and the body would invoke Set.contains using that object as the receiver. - -The ability to reference the method of a specific object provides a convenient way to convert between different functional interface types: - -Callable c = ... -PrivilegedAction a = c::call; -For a reference to an instance method of an arbitrary object, the type to which the method belongs precedes the delimiter, and the invocation's receiver is the first parameter of the functional interface method: - -Function upperfier = String::toUpperCase; -Here, the implicit lambda expression has one parameter, the string to be converted to upper case, which becomes the receiver of the invocation of the toUpperCase() method. - -If the class of the instance method is generic, its type parameters can be provided before the :: delimiter or, in most cases, inferred from the target type. - -Note that the syntax for a static method reference might also be interpreted as a reference to an instance method of a class. The compiler determines which is intended by attempting to identify an applicable method of each kind (noting that the instance method has one less argument). - -For all forms of method references, method type arguments are inferred as necessary, or they can be explicitly provided following the :: delimiter. - -Constructors can be referenced in much the same was as static methods by using the name new: - -SocketImplFactory factory = MySocketImpl::new; -If a class has multiple constructors, the target type's method signature is used to select the best match in the same way that a constructor invocation is resolved. - -For inner classes, no syntax supports explicitly providing an enclosing instance parameter at the site of the constructor reference. - -If the class to instantiate is generic, type arguments can be provided after the class name, or they are inferred as for a "diamond" constructor invocation. - -There is a special syntactic form of constructor references for arrays, which treats arrays as if they had a constructor that accepts an int parameter. For example: - -IntFunction arrayMaker = int[]::new; -int[] array = arrayMaker.apply(10); // creates an int[10] -10. Default and static interface methods -Lambda expressions and method references add a lot of expressiveness to the Java language, but the key to really achieving our goal of making code-as-data patterns convenient and idiomatic is to complement these new features with libraries tailored to take advantage of them. - -Adding new functionality to existing libraries is somewhat difficult in Java SE 7. In particular, interfaces are essentially set in stone once they are published; unless one can update all possible implementations of an interface simultaneously, adding a new method to an interface can cause existing implementations to break. The purpose of default methods (previously referred to as virtual extension methods or defender methods) is to enable interfaces to be evolved in a compatible manner after their initial publication. - -To illustrate, the standard collections API obviously ought to provide new lambda-friendly operations. For example, the removeAll method could be generalized to remove any of a collection's elements for which an arbitrary property held, where the property was expressed as an instance of a functional interface Predicate. But where would this new method be defined? We can't add an abstract method to the Collection interface -- many existing implementations wouldn't know about the change. We could make it a static method in the Collections utility class, but that would relegate these new operations to a sort of second-class status. - -Default methods provide a more object-oriented way to add concrete behavior to an interface. These are a new kind of method: interface method can either be abstract or default. Default methods have an implementation that is inherited by classes that do not override it (see the next section for the details). Default methods in a functional interface don't count against its limit of one abstract method. For example, we could have (though did not) add a skip method to Iterator, as follows: - -interface Iterator { - boolean hasNext(); - E next(); - void remove(); - - default void skip(int i) { - for (; i > 0 && hasNext(); i--) next(); - } -} -Given the above definition of Iterator, all classes that implement Iterator would inherit a skip method. From a client's perspective, skip is just another virtual method provided by the interface. Invoking skip on an instance of a subclass of Iterator that does not provide a body for skip has the effect of invoking the default implementation: calling hasNext and next up to a certain number of times. If a class wants to override skip with a better implementation -- by advancing a private cursor directly, for example, or incorporating an atomicity guarantee -- it is free to do so. - -When one interface extends another, it can add a default to an inherited abstract method, provide a new default for an inherited default method, or reabstract a default method by redeclaring the method as abstract. - -In addition to allowing code in interfaces in the form of default methods, Java SE 8 also introduces the ability to place static methods in interfaces as well. This allows helper methods that are specific to an interface to live with the interface, rather than in a side class (which is often named for the plural of the interface). For example, Comparator acquired static helper methods for making comparators, which takes a function that extracts a Comparable sort key and produces a Comparator: - -public static > -Comparator comparing(Function keyExtractor) { - return (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); -} -11. Inheritance of default methods -Default methods are inherited just like other methods; in most cases, the behavior is just as one would expect. However, when a class's or interface's supertypes provide multiple methods with the same signature, the inheritance rules attempt to resolve the conflict. Two basic principles drive these rules: - -Class method declarations are preferred to interface defaults. This is true whether the class method is concrete or abstract. (Hence the default keyword: default methods are a fallback if the class hierarchy doesn't say anything.) - -Methods that are already overridden by other candidates are ignored. This circumstance can arise when supertypes share a common ancestor. - -As an example of how the second rule comes into play, say the Collection and List interfaces provided different defaults for removeAll, and Queue inherits the default method from Collection; in the following implements clause, the List declaration would have priority over the Collection declaration inherited by Queue: - -class LinkedList implements List, Queue { ... } -In the event that two independently-defined defaults conflict, or a default method conflicts with an abstract method, it is a compilation error. In this case, the programmer must explicitly override the supertype methods. Often, this amounts to picking the preferred default, and declaring a body that invokes the preferred default. An enhanced syntax for super supports the invocation of a particular superinterface's default implementation: - -interface Robot implements Artist, Gun { - default void draw() { Artist.super.draw(); } -} -The name preceding super must refer to a direct superinterface that defines or inherits a default for the invoked method. This form of method invocation is not restricted to simple disambiguation -- it can be used just like any other invocation, in both classes and interfaces. - -In no case does the order in which interfaces are declared in an inherits or extends clause, or which interface was implemented "first" or "more recently", affect inheritance. - -12. Putting it together -The language and library features for Project Lambda were designed to work together. To illustrate, we'll consider the task of sorting a list of people by last name. - -Today we write: - -List people = ... -Collections.sort(people, new Comparator() { - public int compare(Person x, Person y) { - return x.getLastName().compareTo(y.getLastName()); - } -}); -This is a very verbose way to write "sort people by last name"! - -With lambda expressions, we can make this expression more concise: - -Collections.sort(people, - (Person x, Person y) -> x.getLastName().compareTo(y.getLastName())); -However, while more concise, it is not any more abstract; it still burdens the programmer with the need to do the actual comparison (which is even worse when the sort key is a primitive). Small changes to the libraries can help here, such the static comparing method added to Comparator: - -Collections.sort(people, Comparator.comparing((Person p) -> p.getLastName())); -This can be shortened by allowing the compiler to infer the type of the lambda parameter, and importing the comparing method via a static import: - -Collections.sort(people, comparing(p -> p.getLastName())); -The lambda in the above expression is simply a forwarder for the existing method getLastName. We can use method references to reuse the existing method in place of the lambda expression: - -Collections.sort(people, comparing(Person::getLastName)); -Finally, the use of an ancillary method like Collections.sort is undesirable for many reasons: it is more verbose; it can't be specialized for each data structure that implements List; and it undermines the value of the List interface since users can't easily discover the static sort method when inspecting the documentation for List. - -Default methods provide a more object-oriented solution for this problem, where we've added a sort() method to List: - -people.sort(comparing(Person::getLastName)); -Which also reads much more like to the problem statement in the first place: sort the people list by last name. - -If we add a default method reversed() to Comparator, which produces a Comparator that uses the same sort key but in reverse order, we can just as easily express a descending sort: - -people.sort(comparing(Person::getLastName).reversed()); -13. Summary -Java SE 8 adds a relatively small number of new language features -- lambda expressions, method references, default and static methods in interfaces, and more widespread use of type inference. Taken together, though, they enable programmers to express their intent more clearly and concisely with less boilerplate, and enable the development of more powerful, parallel-friendly libraries. \ No newline at end of file diff --git a/3-0-java-core/3-6-3-crazy-regex/README.MD b/3-0-java-core/3-6-3-crazy-regex/README.MD deleted file mode 100644 index 4d42bebf6..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/README.MD +++ /dev/null @@ -1,66 +0,0 @@ -# Crazy Regex - -### Pre-conditions ❗ -You're supposed to know how to work regex and be able to build Patterns and Matchers - -### Objectives -* **build Patterns to extract** necessary parts from text ✅ -* **manipulate** extracted text with **Matcher** object ✅ - -### Regular expressions - sequence of characters that define a search pattern for text - ---- - -There 2 peace pf puzzle: -* Literal characters - I want to match literally the character I specified (like 'a') -* Meta characters - I want to match any character of this kind (more generic/abstract thing) - -Single char - -* \\d -> 0-9 -* \\D -> negate of \\d -* \\w -> A-Za-z0-9 -* \\W -> negate of \\w -* \\s -> whitespace, tab -* \\S -> negate of \\s -* . -> anything but newline -* \\. -> literal dot - - -Quantifiers - modify single characters how many of them you want match in a row -* \* -> Occurs zero or more times -* \+ -> 1 or more -* ? -> zero or one -* {min, max} -> some range -* {n} -> precise quantity - - -Position -* ^ -> beginning -* $ -> end -* \\b -> word boundary - ---- - -Character class -> is the thing that appears in between []. For example [abc] -> match 'a' or 'b' or 'c'. -Another example [-.] -> match dash or period. Here . is not meta character anymore and ^ are special characters inside [] -* [0-5] -> match all numbers from 0 to 5. [^0-5] -> match anything that NOT 0-5 -BUT it works like meta character only when it on first position, otherwise - its literal, [a^bc] - like this - ---- - -Capturing Groups - whenever u do regex search it matches whole result as a group 0. -* \\d{3}-\\d{3}-\\d{4} -> 212-555-1234 = GROUP 0 - -Parentheses can capture a subgroup: -\\d{3}-(\\d{3})-(\\d{4}) where 212-555-1234 = GROUP 0, 555 = GROUP 1, 1234 = GROUP 2 - -We can refer to this groups by $1 ($ when we want to replace) and \1 (within regex itself referring to capture group -it's called back reference) - ---- - -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -
\ No newline at end of file diff --git a/3-0-java-core/3-6-3-crazy-regex/pom.xml b/3-0-java-core/3-6-3-crazy-regex/pom.xml deleted file mode 100644 index 891fe99f2..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 3-0-java-core - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 3-6-3-crazy-regex - - - \ No newline at end of file diff --git a/3-0-java-core/3-6-3-crazy-regex/src/main/java/com/bobocode/se/CrazyRegex.java b/3-0-java-core/3-6-3-crazy-regex/src/main/java/com/bobocode/se/CrazyRegex.java deleted file mode 100644 index e213d3f26..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/src/main/java/com/bobocode/se/CrazyRegex.java +++ /dev/null @@ -1,255 +0,0 @@ -package com.bobocode.se; - -import com.bobocode.util.ExerciseNotCompletedException; - -import java.util.regex.Pattern; - -/** - * {@link CrazyRegex} is an exercise class. Each method returns Pattern class which - * should be created using regex expression. Every method that is not implemented yet - * throws {@link ExerciseNotCompletedException} - *

- * TODO: remove exception and implement each method of this class using {@link Pattern} - * - * @author Andriy Paliychuk - */ -public class CrazyRegex { - - /** - * A Pattern that that finds all words "Curiosity" in text - * - * @return a pattern that looks for the word "Curiosity" - */ - public Pattern findSpecificWord() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds first word in text - * - * @return a pattern that looks for the first word in text - */ - public Pattern findFirstWord() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds last word in text - * - * @return a pattern that looks for the last word in text - */ - public Pattern findLastWord() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all numbers in text. When we have "555-555", "(555)555" and "30th" in text - * our pattern must grab all that numbers: - * "555" - four times, and one "30" - * - * @return a pattern that looks for numbers - */ - public Pattern findAllNumbers() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all dates. For instance: "1971-11-23" - * - * @return a pattern that looks for dates - */ - public Pattern findDates() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds different variations of word "color". - * We are looking for: "color", "colour", "colors", "colours" - * - * @return a pattern that looks for different variations of word "color" - */ - public Pattern findDifferentSpellingsOfColor() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all zip codes in text. - * Zip code is a 5-digit number without any characters or special symbols. - * For example: 72300 - * - * @return a pattern that looks for zip codes - */ - public Pattern findZipCodes() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds different variations of word "link". - * We are looking for: "lynk", "link", "l nk", "l(nk" - * - * @return a pattern that looks for different variations of word "link" - */ - public Pattern findDifferentSpellingsOfLink() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds phone numbers. - * For example: "555-555-5555" - * - * @return a pattern that looks for phone numbers - */ - public Pattern findSimplePhoneNumber() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds numbers with following requirements: - * - inside the number can be only digits from 0 to 5 - * - length 3 - * - * @return a pattern that looks for numbers with length 3 and digits from 0 to 5 in the middle - */ - public Pattern findNumbersFromZeroToFiveWithLengthThree() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all words in text that have length 5 - * - * @return a pattern that looks for the words that have length 5 - */ - public Pattern findAllWordsWithFiveLength() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds words and numbers with following constraints: - * - not shorter than two symbols - * - not longer than three symbols - * - * @return a pattern that looks for words and numbers that not shorter 2 and not longer 3 - */ - public Pattern findAllLettersAndDigitsWithLengthThree() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all words that begin with capital letter - * - * @return a pattern that looks for the words that begin with capital letter - */ - public Pattern findAllWordsWhichBeginWithCapitalLetter() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds only the following abbreviation: - * - AK, AL, AR, AZ, CA, CO, CT, PR, PA, PD - * - * @return a pattern that looks for the abbreviations above - */ - public Pattern findAbbreviation() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all open braces - * - * @return a pattern that looks for all open braces - */ - public Pattern findAllOpenBraces() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds everything inside [] - * - * @return a pattern that looks for everything inside [] - */ - public Pattern findOnlyResources() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all https links in note.txt - * - * @return a pattern that looks for all https links in note.txt - */ - public Pattern findOnlyLinksInNote() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all http links in nasa.json - * - * @return a pattern that looks for all http links in nasa.json - */ - public Pattern findOnlyLinksInJson() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds all .com, .net and .edu emails - * - * @return a pattern that looks for all .com, .net and .edu emails - */ - public Pattern findAllEmails() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds the following examples of phone numbers: - * - 555-555-5555 - * - 555.555.5555 - * - (555)555-5555 - * - * @return a pattern that looks for phone numbers patterns above - */ - public Pattern findAllPatternsForPhoneNumbers() { - throw new ExerciseNotCompletedException(); - } - - /** - * A Pattern that finds only duplicates - * - * @return a pattern that looks for duplicates - */ - public Pattern findOnlyDuplicates() { - throw new ExerciseNotCompletedException(); - } - - /** - * You have a text where all names recorded as first name, last name. - * Create matcher and use method replaceAll to record that names as: - * - last name first name - * - * @return String where all names recorded as last name first name - */ - public String replaceFirstAndLastNames(String names) { - throw new ExerciseNotCompletedException(); - } - - /** - * You have a text with phone numbers. - * Create matcher and use method replaceAll to replace last digits: - * - 555-XXX-XXXX - * - * @return String where in all phone numbers last 7 digits replaced to X - */ - public String replaceLastSevenDigitsOfPhoneNumberToX(String phones) { - throw new ExerciseNotCompletedException(); - } - - /** - * You have a text with resources and links to those resources: - * - [Bobocode](https://www.bobocode.com) - * Create matcher and use method replaceAll to get the following result: - * - Bobocode - * - * @return String where all resources embraced in href - */ - public String insertLinksAndResourcesIntoHref(String links) { - throw new ExerciseNotCompletedException(); - } -} diff --git a/3-0-java-core/3-6-3-crazy-regex/src/test/java/com/bobocode/se/CrazyRegexTest.java b/3-0-java-core/3-6-3-crazy-regex/src/test/java/com/bobocode/se/CrazyRegexTest.java deleted file mode 100644 index e0d2d50fb..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/src/test/java/com/bobocode/se/CrazyRegexTest.java +++ /dev/null @@ -1,246 +0,0 @@ -package com.bobocode.se; - -import lombok.SneakyThrows; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.joining; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -/** - * A test class for {@link CrazyRegex}. - * - * @author Andriy Paliychuk - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class CrazyRegexTest { - - private final CrazyRegex crazyRegex = new CrazyRegex(); - - private final String text; - private final String json; - - public CrazyRegexTest() { - this.text = readWholeFile("note.txt"); - this.json = readWholeFile("nasa.json"); - } - - @Test - @Order(1) - void findSpecificWord() { - String result = regexChecker(crazyRegex.findSpecificWord(), json); - assertThat(result).isEqualTo("\nCuriosity\nCuriosity\nCuriosity"); - } - - @Test - @Order(2) - void findFirstWord() { - String result = regexChecker(crazyRegex.findFirstWord(), text); - assertThat(result).isEqualTo("\nThe"); - } - - @Test - @Order(3) - void findLastWord() { - String result = regexChecker(crazyRegex.findLastWord(), text); - assertThat(result).isEqualTo("\nfish"); - } - - @Test - @Order(4) - void findAllNumbers() { - String result = regexChecker(crazyRegex.findAllNumbers(), text); - assertThat(result).isEqualTo("\n01001\n03148\n02132\n412\n555\n1212\n412\n555" + - "\n1234\n412\n555\n1234\n646\n555\n1234\n1"); - } - - @Test - @Order(5) - void findDates() { - String result = regexChecker(crazyRegex.findDates(), json); - assertThat(result).isEqualTo("\n2015-05-30\n2012-08-06\n2011-11-26\n2015-05-30\n2012-08-06\n" + - "2011-11-26\n2015-05-30\n2012-08-06\n2011-11-26"); - } - - @Test - @Order(6) - void findDifferentSpellingsOfColor() { - String result = regexChecker(crazyRegex.findDifferentSpellingsOfColor(), text); - assertThat(result).isEqualTo("\ncolors\ncolours\ncolour"); - } - - @Test - @Order(7) - void findZipCodes() { - String result = regexChecker(crazyRegex.findZipCodes(), text); - assertThat(result).isEqualTo("\n 01001 \n 03148 \n 02132 "); - } - - @Test - @Order(8) - void findDifferentSpellingsOfLink() { - String result = regexChecker(crazyRegex.findDifferentSpellingsOfLink(), text); - assertThat(result).isEqualTo("\nlynk\nlink\nl nk\nl(nk"); - } - - @Test - @Order(9) - void findSimplePhoneNumber() { - String result = regexChecker(crazyRegex.findSimplePhoneNumber(), text); - assertThat(result).isEqualTo("\n412-555-1234"); - } - - @Test - @Order(10) - void findNumbersFromZeroToFiveWithLengthThree() { - String result = regexChecker(crazyRegex.findNumbersFromZeroToFiveWithLengthThree(), text); - assertThat(result).isEqualTo("\n010\n031\n021\n412\n555\n121\n412" + - "\n555\n123\n412\n555\n123\n555\n123"); - } - - @Test - @Order(11) - void findAllWordsWithFiveLength() { - String result = regexChecker(crazyRegex.findAllWordsWithFiveLength(), json); - assertThat(result).isEqualTo("\nFront\nrover\nFront\nrover\nrover"); - } - - @Test - @Order(12) - void findAllLettersAndDigitsWithLengthThree() { - String result = regexChecker(crazyRegex.findAllLettersAndDigitsWithLengthThree(), text); - assertThat(result).isEqualTo("\nThe\nof\nthe\nand\nthe\nnot\nThe\nis\ndon\nyou\nnk\nnk\nThe\nCA\nAK\nPA\n412" + - "\n555\ncom\n412\n555\n412\n555\n646\n555\nof\ncom\nnet\nor\nnyu\nedu\n1Z\naaa\nOf\nwww\ncom\ncom\nwww\ncom" + - "\nis\nis\nam\nnot\nnot\nwhy\nwhy\nam\nok\ncat\ncat\ndog\ndog"); - } - - @Test - @Order(13) - void findAllWordsWhichBeginWithCapitalLetter() { - String result = regexChecker(crazyRegex.findAllWordsWhichBeginWithCapitalLetter(), json); - assertThat(result).isEqualTo("\nFront\nHazard\nAvoidance\nCamera" + - "\nCuriosity\nFront\nHazard\nAvoidance\nCamera\nCuriosity\nRear\nHazard\nAvoidance\nCamera\nCuriosity"); - } - - @Test - @Order(14) - void findAbbreviation() { - String result = regexChecker(crazyRegex.findAbbreviation(), text); - assertThat(result).isEqualTo("\nCA\nAK\nPA"); - } - - @Test - @Order(15) - void findAllOpenBraces() { - String result = regexChecker(crazyRegex.findAllOpenBraces(), text); - assertThat(result).isEqualTo("\n{{{\n{{\n{"); - } - - @Test - @Order(16) - void findOnlyResources() { - String result = regexChecker(crazyRegex.findOnlyResources(), text); - assertThat(result).isEqualTo("\nGoogle\nStackOverflow\nYoutube"); - } - - @Test - @Order(17) - void findOnlyLinksInNote() { - String result = regexChecker(crazyRegex.findOnlyLinksInNote(), text); - assertThat(result).isEqualTo("\nhttps://www.google.com\nhttps://stackoverflow.com\nhttps://www.youtube.com"); - } - - @Test - @Order(18) - void findOnlyLinksInJson() { - String result = regexChecker(crazyRegex.findOnlyLinksInJson(), json); - assertThat(result).isEqualTo( - "\nhttp://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FLB_486265257EDR_F0481570FHAZ00323M_.JPG\n" + - "http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FRB_486265257EDR_F0481570FHAZ00323M_.JPG\n" + - "http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/rcam/RLB_486265291EDR_F0481570RHAZ00323M_.JPG" - ); - } - - @Test - @Order(19) - void findAllEmails() { - String result = regexChecker(crazyRegex.findAllEmails(), text); - assertThat(result).isEqualTo("\njohnsmith@yahoo.com\nterek.koval@gmail.com\nterek@koval.net" + - "\nterek.koval@nyu.edu"); - } - - @Test - @Order(20) - void findAllPatternsForPhoneNumbers() { - String result = regexChecker(crazyRegex.findAllPatternsForPhoneNumbers(), text); - assertThat(result).isEqualTo("\n(412)555-1212\n412-555-1234\n646.555.1234"); - } - - @Test - @Order(21) - void findOnlyDuplicates() { - String result = regexChecker(crazyRegex.findOnlyDuplicates(), text); - assertThat(result).isEqualTo("\nis is\ntext text\ndouble double\nI I\nnot not\nwhy why" + - "\ncat cat\ndog\ndog\nfish fish"); - } - - @Test - @Order(22) - void replaceFirstAndLastNames() { - String names = "Tarasenko, Nazar ... Petrashyk, Petro ... Zlepko, Andrii"; - String result = crazyRegex.replaceFirstAndLastNames(names); - assertThat(result).isEqualTo("Nazar Tarasenko ... Petro Petrashyk ... Andrii Zlepko"); - } - - @Test - @Order(23) - void replaceLastSevenDigitsOfPhoneNumberToX() { - String phones = "(948)333-5656 1235-889-7897 111.747.6236"; - String result = crazyRegex.replaceLastSevenDigitsOfPhoneNumberToX(phones); - assertThat(result).isEqualTo("948-XXX-XXXX 1235-XXX-XXXX 111-XXX-XXXX"); - } - - @Test - @Order(24) - void insertLinksAndResourcesIntoHref() { - String links = "[Bobocode](https://www.bobocode.com)" + - "\n[LinkedIn](https://www.linkedin.com)" + - "\n[Netflix](https://www.netflix.com)"; - String result = crazyRegex.insertLinksAndResourcesIntoHref(links); - assertThat(result).isEqualTo( - "Bobocode\n" + - "LinkedIn\n" + - "Netflix" - ); - } - - private String regexChecker(Pattern pattern, String str2WorkWith) { - Matcher matcher = pattern.matcher(str2WorkWith); - StringBuilder stringBuilder = new StringBuilder(); - while (matcher.find()) { - if (matcher.group().length() != 0) { - stringBuilder.append("\n").append(matcher.group()); - } - } - return stringBuilder.toString(); - } - - @SneakyThrows - private String readWholeFile(String fileName) { - Path filePath = Paths.get(CrazyRegex.class.getClassLoader() - .getResource(fileName) - .toURI()); - try (Stream fileLinesStream = Files.lines(filePath)) { - return fileLinesStream.collect(joining("\n")); - } - } -} \ No newline at end of file diff --git a/3-0-java-core/3-6-3-crazy-regex/src/test/resources/nasa.json b/3-0-java-core/3-6-3-crazy-regex/src/test/resources/nasa.json deleted file mode 100644 index e21232795..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/src/test/resources/nasa.json +++ /dev/null @@ -1,23 +0,0 @@ -{"photos":[ - {"id":102693, - "sol":1000, - "camera":{"id":20,"name":"FHAZ","rover_id":5,"full_name":"Front Hazard Avoidance Camera"}, - "img_src":"http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FLB_486265257EDR_F0481570FHAZ00323M_.JPG", - "earth_date":"2015-05-30", - "rover":{"id":5,"name":"Curiosity","landing_date":"2012-08-06","launch_date":"2011-11-26","status":"active"} - }, - {"id":102694, - "sol":1000, - "camera":{"id":20,"name":"FHAZ","rover_id":5,"full_name":"Front Hazard Avoidance Camera"}, - "img_src":"http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FRB_486265257EDR_F0481570FHAZ00323M_.JPG", - "earth_date":"2015-05-30", - "rover":{"id":5,"name":"Curiosity","landing_date":"2012-08-06","launch_date":"2011-11-26","status":"active"} - }, - {"id":102850, - "sol":1000, - "camera":{"id":21,"name":"RHAZ","rover_id":5,"full_name":"Rear Hazard Avoidance Camera"}, - "img_src":"http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/rcam/RLB_486265291EDR_F0481570RHAZ00323M_.JPG", - "earth_date":"2015-05-30", - "rover":{"id":5,"name":"Curiosity","landing_date":"2012-08-06","launch_date":"2011-11-26","status":"active"} - } -]} \ No newline at end of file diff --git a/3-0-java-core/3-6-3-crazy-regex/src/test/resources/note.txt b/3-0-java-core/3-6-3-crazy-regex/src/test/resources/note.txt deleted file mode 100644 index 2ab940b50..000000000 --- a/3-0-java-core/3-6-3-crazy-regex/src/test/resources/note.txt +++ /dev/null @@ -1,9 +0,0 @@ -The colors of the rainbow have many colours and the rainbow does not have a single colour -The lynk is quite a link don't you think? l nk l(nk -The Collin Richardson CA 01001 AK 03148 PA 02132 (412)555-1212 johnsmith@yahoo.com 412-555-1234 412 555-1234 646.555.1234 -I know email addresses of fascinating people like terek.koval@gmail.com terek@koval.net or -terek.koval@nyu.edu - 1Z aaa **** *** {{{ {{ { Of -[Google](https://www.google.com)[StackOverflow](https://stackoverflow.com)[Youtube](https://www.youtube.com) -This is is some text text with double double words some where I I I am not not sure why why I am typing ok? cat cat dog -dog fish fish \ No newline at end of file diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/README.MD b/4-0-object-oriented-programming/4-3-1-flight-search/README.MD deleted file mode 100644 index 889f6f1ee..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/README.MD +++ /dev/null @@ -1,26 +0,0 @@ -# Flight search -Improve your OOP skills and learn the power on polymorphism by inverting the compile-time dependency 💪 - -### Task -`FlighService` and package `service` represent a component of the system that holds a business logic. `FlightDao` -and package `data` represent a component of the system that implements data access layer. Your job is to implement -the *todo* section of those classes **following OOP design principles.** - -### Pre-conditions ❗️ -You're supposed to be familiar polymorphism and Java interfaces - -### Objectives -* **implement `FlightDao`** (data access object) methods using a simple `HashMap` ✅ -* **implement service method** that allows to **register flight** using DAO ✅ -* **implement service method** that allows **search for a flight** using DAO ✅ -* **invert the dependency** between service and DAO by adding an interface ✅ - -### Related materials ℹ️ - * [SOLID](https://en.wikipedia.org/wiki/SOLID) - ---- - -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/pom.xml b/4-0-object-oriented-programming/4-3-1-flight-search/pom.xml deleted file mode 100644 index d9cb07346..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 4-0-object-oriented-programming - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 4-3-1-flight-search - - - \ No newline at end of file diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/FlightDao.java b/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/FlightDao.java deleted file mode 100644 index 3e58c3b33..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/FlightDao.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.bobocode.oop.data; - -import com.bobocode.util.ExerciseNotCompletedException; - -import java.util.HashSet; -import java.util.Set; - -/** - * {@link FlightDao} represents a Data Access Object (DAO) for flights. The implementation is simplified, so it just - * uses {@link HashSet} to store flight numbers. - *

- * todo: 1. Implement a method {@link FlightDao#register(String)} that store new flight number into the set - * todo: 2. Implement a method {@link FlightDao#findAll()} that returns a set of all flight numbers - */ -public class FlightDao { - private Set flights = new HashSet<>(); - - /** - * Stores a new flight number - * - * @param flightNumber a flight number to store - * @return {@code true} if a flight number was stored, {@code false} otherwise - */ - public boolean register(String flightNumber) { - throw new ExerciseNotCompletedException();// todo: implement this method - } - - /** - * Returns all stored flight numbers - * - * @return a set of flight numbers - */ - public Set findAll() { - throw new ExerciseNotCompletedException();// todo: implement this method - } - -} diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/factory/FlightServiceFactory.java b/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/factory/FlightServiceFactory.java deleted file mode 100644 index 8cd2ed673..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/factory/FlightServiceFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.bobocode.oop.factory; - -import com.bobocode.oop.service.FlightService; -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link FlightServiceFactory} is used to create an instance of {@link FlightService} - *

- * todo: 1. Implement method {@link FlightServiceFactory#creteFlightService()} - */ -public class FlightServiceFactory { - - /** - * Create a new instance of {@link FlightService} - * - * @return FlightService - */ - public FlightService creteFlightService() { - throw new ExerciseNotCompletedException(); - } -} diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/service/FlightService.java b/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/service/FlightService.java deleted file mode 100644 index b31cd8f07..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/service/FlightService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.bobocode.oop.service; - -import com.bobocode.util.ExerciseNotCompletedException; - -import java.util.List; - -/** - * {@link FlightService} provides an API that allows to manage flight numbers - *

- * todo: 1. Using {@link com.bobocode.oop.data.FlightDao} implement method {@link FlightService#registerFlight(String)} - * todo: 2. Using {@link com.bobocode.oop.data.FlightDao} implement method {@link FlightService#searchFlights(String)} - */ -public class FlightService { - - /** - * Adds a new flight number - * - * @param flightNumber a flight number to add - * @return {@code true} if a flight number was added, {@code false} otherwise - */ - public boolean registerFlight(String flightNumber) { - throw new ExerciseNotCompletedException(); - } - - /** - * Returns all flight numbers that contains a provided key. - * - * @param query a search query - * @return a list of found flight numbers - */ - public List searchFlights(String query) { - throw new ExerciseNotCompletedException(); - } -} diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/src/test/java/com/bobocode/oop/FlightServiceTest.java b/4-0-object-oriented-programming/4-3-1-flight-search/src/test/java/com/bobocode/oop/FlightServiceTest.java deleted file mode 100644 index 60ca7e785..000000000 --- a/4-0-object-oriented-programming/4-3-1-flight-search/src/test/java/com/bobocode/oop/FlightServiceTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.bobocode.oop; - -import com.bobocode.oop.factory.FlightServiceFactory; -import com.bobocode.oop.service.FlightService; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class FlightServiceTest { - - private FlightService flightService = new FlightServiceFactory().creteFlightService(); - - @Test - public void testRegisterFlight() { - boolean registered = flightService.registerFlight("PR344"); - - assertTrue(registered); - } - - @Test - public void testRegisterSameFlightTwice() { - flightService.registerFlight("RB122"); - - boolean registeredSecondTime = flightService.registerFlight("RB122"); - - assertFalse(registeredSecondTime); - } - - @Test - public void testSearchExistingFlightByFullNumber() { - flightService.registerFlight("OL234"); - flightService.registerFlight("KM23234"); - flightService.registerFlight("LTE114"); - flightService.registerFlight("BRT14"); - - List foundFlights = flightService.searchFlights("LTE114"); - - assertEquals(1, foundFlights.size()); - assertEquals("LTE114", foundFlights.get(0)); - } - - @Test - public void testSearchNonExistingFlight() { - List foundFlights = flightService.searchFlights("XXX"); - - assertNotNull(foundFlights); - } - - @Test - public void testSearchFlights() { - flightService.registerFlight("OR1214"); - flightService.registerFlight("BTR14"); - flightService.registerFlight("BMK198"); - flightService.registerFlight("RLR198"); - - List foundFlights = flightService.searchFlights("R1"); - - assertTrue(foundFlights.contains("OR1214")); - assertTrue(foundFlights.contains("BTR14")); - assertTrue(foundFlights.contains("RLR198")); - assertEquals(3, foundFlights.size()); - } -} diff --git a/4-0-object-oriented-programming/README.md b/4-0-object-oriented-programming/README.md deleted file mode 100644 index cfc96c23d..000000000 --- a/4-0-object-oriented-programming/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Java Object-Oriented Programming -Build strong object-oriented programming skills needed for enterprise Java development 💪 \ No newline at end of file diff --git a/4-0-object-oriented-programming/pom.xml b/4-0-object-oriented-programming/pom.xml deleted file mode 100644 index b15dc549d..000000000 --- a/4-0-object-oriented-programming/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - pom - - 4-3-1-flight-search - - - - com.bobocode - java-fundamentals-exercises - 1.0-SNAPSHOT - - 4-0-object-oriented-programming - - - - - com.bobocode - java-fundamentals-util - 1.0-SNAPSHOT - compile - - - - \ No newline at end of file diff --git a/6-0-test-driven-development/6-1-1-stack/README.md b/6-0-test-driven-development/6-1-1-stack/README.md deleted file mode 100644 index 768c66645..000000000 --- a/6-0-test-driven-development/6-1-1-stack/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Stack exercise :muscle: -Improve your TDD skill implementing Stack - -### Task -**Stack** is last in, first out (LIFO) collection of elements. Your job is to implement the interface `Stack` - using TDD discipline - -### Pre-conditions :heavy_exclamation_mark: -You're supposed to know [The Three laws of TDD](https://github.com/bobocode-projects/java-fundamentals-exercises#the-three-laws-of-tdd) relink, - be familiar with Stack data structure, and be able to write Java code - -### How to start :question: -* Just clone the repository and start implementing `Stack` interface following *three laws of TDD* -* If you don't have enough knowledge about this domain, check out the [links below](#related-materials-information_source) -* Don't worry if you got stuck, checkout the [exercise/completed](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/exercise/completed) branch and see the final implementation - -### Related materials :information_source: - * [Як виробити звичку писати тести? (Bobocode channel )](https://youtu.be/L_CiX9C51BI) - * [Stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)) - * [The Three Laws of TDD](https://www.youtube.com/watch?v=qkblc5WRn-U&t=3476s) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -

\ No newline at end of file diff --git a/6-0-test-driven-development/6-1-1-stack/pom.xml b/6-0-test-driven-development/6-1-1-stack/pom.xml deleted file mode 100644 index e1cca8424..000000000 --- a/6-0-test-driven-development/6-1-1-stack/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 6-0-test-driven-development - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 6-1-1-stack - - - \ No newline at end of file diff --git a/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/LinkedStack.java b/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/LinkedStack.java deleted file mode 100644 index a7bc5fc23..000000000 --- a/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/LinkedStack.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.bobocode.tdd; - -import com.bobocode.util.ExerciseNotCompletedException; - -public class LinkedStack implements Stack { - @Override - public void push(T element) { - throw new ExerciseNotCompletedException(); // todo - } - - @Override - public T pop() { - throw new ExerciseNotCompletedException(); // todo - } - - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo - } - - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo - } -} diff --git a/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/Stack.java b/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/Stack.java deleted file mode 100644 index 9215e86a9..000000000 --- a/6-0-test-driven-development/6-1-1-stack/src/main/java/com/bobocode/tdd/Stack.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.bobocode.tdd; - -/** - * - * Stack is a data structure that follows "last in, first out" rule (LIFO). - */ -public interface Stack { - /** - * Adds an element to the begining of the stack. - * - * @param element the element to add - */ - void push(T element); - - /** - * Retrieves and removes stack head. - * - * @return an element that was retrieved from the head or null if stack is empty - */ - T pop(); - - /** - * Returns a size of the stack. - * - * @return an integer value that is a size of stack - */ - int size(); - - /** - * Checks if the stack is empty. - * - * @return {@code true} if the stack is empty, returns {@code false} if it's not - */ - boolean isEmpty(); -} diff --git a/6-0-test-driven-development/6-1-1-stack/src/test/java/com/bobocode/tdd/StackTest.java b/6-0-test-driven-development/6-1-1-stack/src/test/java/com/bobocode/tdd/StackTest.java deleted file mode 100644 index 8d01a406f..000000000 --- a/6-0-test-driven-development/6-1-1-stack/src/test/java/com/bobocode/tdd/StackTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.bobocode.tdd; - -public class StackTest { -} diff --git a/6-0-test-driven-development/6-1-2-linked-list/README.MD b/6-0-test-driven-development/6-1-2-linked-list/README.MD deleted file mode 100644 index 57bd8c20f..000000000 --- a/6-0-test-driven-development/6-1-2-linked-list/README.MD +++ /dev/null @@ -1,32 +0,0 @@ -# Linked List exercise 💪 -Improve your TDD skills implementing LinkedList - -### Task -`List` is an API that represents a well-known data structure. Your job is to -implement the *todo* section of the class `LinkedList` **following TDD rules**. Please note, that your implementation -should be based on **singly liked nodes.** It means that you should create your own class `Node` -that will hold list elements. - -To verify your implementation check if your `LinkedListTest.java` provides full **(100%) code coverage** and compare it -with **completed exercise** - -### Pre-conditions❗ -You're supposed to know [The Three laws of TDD](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/6-0-test-driven-development#the-three-laws-of-tdd), - be familiar with Linked List data structure, and be able to write Java code - -### How to start❓ -* Just clone the repository and create a branch **exercise/your_username** if you want your code to be reviewed -* Start implementing the **todo** section and verify your changes by running tests -* If you don't have enough knowledge about this domain, check out the [links below](#related-materials-information_source) -* Don't worry if you got stuck, checkout the **exercise/completed** branch and see the final implementation - -### Related materials ℹ - * [Linked Lists]() todo: add link on LinkedList materials - * [Як виробити звичку писати тести? (Bobocode channel )](https://youtu.be/L_CiX9C51BI) - * [The Three Laws of TDD](https://www.youtube.com/watch?v=qkblc5WRn-U&t=3476s) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -
\ No newline at end of file diff --git a/6-0-test-driven-development/6-1-2-linked-list/pom.xml b/6-0-test-driven-development/6-1-2-linked-list/pom.xml deleted file mode 100644 index 20b924ac4..000000000 --- a/6-0-test-driven-development/6-1-2-linked-list/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 6-0-test-driven-development - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 6-1-2-linked-list - - - \ No newline at end of file diff --git a/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/LinkedList.java b/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/LinkedList.java deleted file mode 100644 index 275b70a4b..000000000 --- a/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/LinkedList.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.bobocode.tdd; - - -import com.bobocode.util.ExerciseNotCompletedException; - -/** - * {@link LinkedList} is a list implementation that is based on singly linked generic nodes. A node is implemented as - * inner static class {@link Node}. - * - * @param generic type parameter - */ -public class LinkedList implements List { - - /** - * This method creates a list of provided elements - * - * @param elements elements to add - * @param generic type - * @return a new list of elements the were passed as method parameters - */ - public static List of(T... elements) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds an element to the end of the list. - * - * @param element element to add - */ - @Override - public void add(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Adds a new element to the specific position in the list. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index an index of new element - * @param element element to add - */ - @Override - public void add(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Changes the value of an list element at specific position. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index an position of element to change - * @param element a new element value - */ - @Override - public void set(int index, T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Retrieves an elements by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index element index - * @return an element value - */ - @Override - public T get(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the first element of the list. Operation is performed in constant time O(1) - * - * @return the first element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getFirst() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the last element of the list. Operation is performed in constant time O(1) - * - * @return the last element of the list - * @throws java.util.NoSuchElementException if list is empty - */ - @Override - public T getLast() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes an elements by its position index. In case provided index in out of the list bounds it - * throws {@link IndexOutOfBoundsException} - * - * @param index element index - * @return deleted element - */ - @Override - public T remove(int index) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - - /** - * Checks if a specific exists in he list - * - * @return {@code true} if element exist, {@code false} otherwise - */ - @Override - public boolean contains(T element) { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Checks if a list is empty - * - * @return {@code true} if list is empty, {@code false} otherwise - */ - @Override - public boolean isEmpty() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Returns the number of elements in the list - * - * @return number of elements - */ - @Override - public int size() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } - - /** - * Removes all list elements - */ - @Override - public void clear() { - throw new ExerciseNotCompletedException(); // todo: implement this method - } -} diff --git a/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/List.java b/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/List.java deleted file mode 100644 index 532303a93..000000000 --- a/6-0-test-driven-development/6-1-2-linked-list/src/main/java/com/bobocode/tdd/List.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.bobocode.tdd; - - -public interface List { - void add(T element); - - void add(int index, T element); - - void set(int index, T element); - - T get(int index); - - T getFirst(); - - T getLast(); - - T remove(int index); - - boolean contains(T element); - - boolean isEmpty(); - - int size(); - - void clear(); - -} diff --git a/6-0-test-driven-development/6-1-2-linked-list/src/test/java/com/bobocode/tdd/LinkedListTest.java b/6-0-test-driven-development/6-1-2-linked-list/src/test/java/com/bobocode/tdd/LinkedListTest.java deleted file mode 100644 index 4477db6b4..000000000 --- a/6-0-test-driven-development/6-1-2-linked-list/src/test/java/com/bobocode/tdd/LinkedListTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.bobocode.tdd; - -public class LinkedListTest { -} diff --git a/6-0-test-driven-development/6-1-3-binary-search-tree/README.md b/6-0-test-driven-development/6-1-3-binary-search-tree/README.md deleted file mode 100644 index ebac8356a..000000000 --- a/6-0-test-driven-development/6-1-3-binary-search-tree/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Binary Search Tree exercise :muscle: -Improve your TDD skill implementing Binary Search Tree - -### Task -**Binary Search Tree (BST)** is an ordered (sorted) data structure. Your job is to implement the interface `BinarySearchTree` - by practicing TDD discipline - -### Pre-conditions :heavy_exclamation_mark: -You're supposed to know [The Three laws of TDD](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/6-0-test-driven-development#the-three-laws-of-tdd), -be familiar with [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree) data structure, -and understand [Recursion](https://en.wikipedia.org/wiki/Recursion_(computer_science)) - -### How to start :question: -* Just clone the repository and start implementing `BinarySearchTree` interface following *three laws of TDD* -* If you don't have enough knowledge about this domain, check out the [links below](#related-materials-information_source) -* Don't worry if you got stuck, checkout branch **completed** and see the final implementation - -### Related materials :information_source: - * [Як виробити звичку писати тести? ](https://youtu.be/L_CiX9C51BI) - * [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree) - * [The Three Laws of TDD](https://www.youtube.com/watch?v=qkblc5WRn-U&t=3476s) - ---- -#### 🆕 First time here? – [See Introduction](https://github.com/bobocode-projects/java-fundamentals-exercises/tree/main/0-0-intro#introduction) - -## -
\ No newline at end of file diff --git a/6-0-test-driven-development/6-1-3-binary-search-tree/pom.xml b/6-0-test-driven-development/6-1-3-binary-search-tree/pom.xml deleted file mode 100644 index 442face24..000000000 --- a/6-0-test-driven-development/6-1-3-binary-search-tree/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 6-0-test-driven-development - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 6-1-3-binary-search-tree - - - \ No newline at end of file diff --git a/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/BinarySearchTree.java b/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/BinarySearchTree.java deleted file mode 100644 index cea1ceffa..000000000 --- a/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/BinarySearchTree.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.bobocode.tdd; - -import java.util.function.Consumer; - -public interface BinarySearchTree { - /** - * insert an element - * @return true if element did not exist in the tree and was inserted successfully - */ - boolean insert(T element); - - /** - * @return true if tree contains element - */ - boolean contains(T element); - - /** - * @return number of elements in the tree - */ - int size(); - - /** - * @return max. number of transition between root node and any other node; 0 - if tree is empty or contains 1 element - */ - int depth(); - - /** - * traverse the tree in element's natural order - * @param consumer accepts ref. to node during traversing - */ - void inOrderTraversal(Consumer consumer); -} diff --git a/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/RecursiveBinarySearchTree.java b/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/RecursiveBinarySearchTree.java deleted file mode 100644 index a9e368a97..000000000 --- a/6-0-test-driven-development/6-1-3-binary-search-tree/src/main/java/com/bobocode/tdd/RecursiveBinarySearchTree.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.bobocode.tdd; - -import com.bobocode.util.ExerciseNotCompletedException; - -import java.util.function.Consumer; - -public class RecursiveBinarySearchTree implements BinarySearchTree { - - public static RecursiveBinarySearchTree of(T... elements) { - throw new ExerciseNotCompletedException(); - } - - @Override - public boolean insert(T element) { - throw new ExerciseNotCompletedException(); - } - - @Override - public boolean contains(T element) { - throw new ExerciseNotCompletedException(); - } - - @Override - public int size() { - throw new ExerciseNotCompletedException(); - } - - @Override - public int depth() { - throw new ExerciseNotCompletedException(); - } - - @Override - public void inOrderTraversal(Consumer consumer) { - throw new ExerciseNotCompletedException(); - } -} diff --git a/6-0-test-driven-development/6-1-3-binary-search-tree/src/test/java/com/bobocode/tdd/BinarySearchTreeTest.java b/6-0-test-driven-development/6-1-3-binary-search-tree/src/test/java/com/bobocode/tdd/BinarySearchTreeTest.java deleted file mode 100644 index 6c6fb5478..000000000 --- a/6-0-test-driven-development/6-1-3-binary-search-tree/src/test/java/com/bobocode/tdd/BinarySearchTreeTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.bobocode.tdd; - -class BinarySearchTreeTest { - -} diff --git a/6-0-test-driven-development/README.md b/6-0-test-driven-development/README.md deleted file mode 100644 index 84d65f5c5..000000000 --- a/6-0-test-driven-development/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Test-Driven Development -Build strong TDD skills needed for enterprise Java development 💪 - -## -### The three laws of TDD -1. You should not write production code until you have written a failing unit test -2. You should not write more of a unit test than is sufficient to fail -3. You should not write more production code than is sufficient to pass the failing test - diff --git a/6-0-test-driven-development/pom.xml b/6-0-test-driven-development/pom.xml deleted file mode 100644 index 40c5e703a..000000000 --- a/6-0-test-driven-development/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - java-fundamentals-exercises - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 6-0-test-driven-development - pom - - 6-1-1-stack - 6-1-2-linked-list - 6-1-3-binary-search-tree - - - - - - com.bobocode - java-fundamentals-util - 1.0-SNAPSHOT - compile - - - - \ No newline at end of file