From 50e1c90eeb0202143c96d94df4ea43805dc1f765 Mon Sep 17 00:00:00 2001 From: Jhil Kumari Date: Thu, 27 Feb 2025 13:01:57 +0530 Subject: [PATCH] Completed all the topic specific tasks mentioned in the module --- .../main/java/com/bobocode/basics/Box.java | 10 +- .../java/com/bobocode/basics/BoxDemoApp.java | 6 +- .../java/com/bobocode/basics/BoxTest.java | 6 +- .../com/bobocode/basics/CrazyGenerics.java | 119 +++++++++++++----- .../com/bobocode/basics/util/BaseEntity.java | 8 ++ .../bobocode/basics/CrazyGenericsTest.java | 11 +- .../basics/HeterogeneousMaxHolder.java | 24 +++- .../main/java/com/bobocode/fp/Functions.java | 6 +- .../java/com/bobocode/fp/SumOfSquares.java | 8 +- .../java/com/bobocode/fp/CrazyLambdas.java | 62 ++++++--- .../java/com/bobocode/fp/CrazyStreams.java | 68 +++++++--- .../java/com/bobocode/fp/CrazyOptionals.java | 72 ++++++++--- .../java/com/bobocode/fp/PrimeNumbers.java | 24 +++- .../main/java/com/bobocode/model/Account.java | 66 ++++++++++ 14 files changed, 372 insertions(+), 118 deletions(-) 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..8ade1196f 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,12 +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); - intBox.setValue("abc"); // this should not be allowed +// 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-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java index 76e0f385a..0f3716548 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java @@ -41,7 +41,7 @@ void typeParameterIsNotBounded() { @SneakyThrows @Order(4) @DisplayName("Field \"value\" is \"T\"") - void valueFieldIsGeneric() { + void valueFieldIsGeneric() throws NoSuchFieldException { var valueField = Box.class.getDeclaredField("value"); var genericType = valueField.getGenericType(); @@ -64,7 +64,7 @@ void constructorParameterIsGeneric() { @SneakyThrows @Order(6) @DisplayName("Getter return type is \"T\"") - void getterReturnTypeIsGeneric() { + void getterReturnTypeIsGeneric() throws NoSuchMethodException { var getter = Box.class.getDeclaredMethod("getValue"); assertThat(getter.getGenericReturnType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); @@ -74,7 +74,7 @@ void getterReturnTypeIsGeneric() { @SneakyThrows @Order(7) @DisplayName("Setter parameter type is \"T\"") - void setterParameterIsGeneric() { + void setterParameterIsGeneric() throws NoSuchMethodException { var setter = Box.class.getDeclaredMethod("setValue", Object.class); assert (setter.getParameters().length == 1); var parameter = setter.getParameters()[0]; 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..35253e7b7 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 @@ -5,10 +5,8 @@ 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 +31,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 +43,18 @@ 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 +64,9 @@ public static class Limited { * @param – source object type * @param - converted result type */ - public interface Converter { // todo: introduce type parameters + public interface Converter { // todo: introduce type parameters // todo: add convert method + R convert(T source); } /** @@ -70,10 +76,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 +88,14 @@ 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) { + // todo: update parameter and implement the method + if(val.compareTo(max) > 0){ + max = val; + } } - public Object getMax() { + public T getMax() { return max; } } @@ -97,8 +106,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 +117,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 +129,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 +142,10 @@ 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 + interface ComparableCollection extends Collection, Comparable> { // todo: refactor it to make generic and provide a default impl of compareTo + default int compareTo(Collection other) { // Change parameter type + return Integer.compare(this.size(), other.size()); + } } /** @@ -147,7 +159,7 @@ static class CollectionUtil { * * @param list */ - public static void print(List 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)); } @@ -160,8 +172,14 @@ 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) { + // todo: refactor parameter and implement method + for (BaseEntity entity : entities) { + if (entity.getUuid() == null) { + return true; + } + } + return false; } /** @@ -173,8 +191,14 @@ 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) { + // todo: add method parameters and implement the logic + for (BaseEntity entity : entities) { + if (!validationPredicate.test(entity)) { + return false; + } + } + return true; } /** @@ -187,8 +211,17 @@ 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; + UUID targetUUID = targetEntity.getUuid(); + for (T entity : entities) { + UUID entityUUID = entity.getUuid(); + if (entityUUID.equals(targetUUID)) { + count++; + } + } + return count > 1; } /** @@ -201,7 +234,15 @@ 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){ + T max = null; + for (T element : elements) { + if (max == null || comparator.compare(element, max) > 0) { + max = element; + } + } + return Optional.ofNullable(max); + } /** * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the * one that is the most recently created. If collection is empty, @@ -215,7 +256,10 @@ public static boolean hasDuplicates() { * @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, Comparator.comparing(BaseEntity::getCreatedOn)) + .orElseThrow(NoSuchElementException::new); + } /** * An util method that allows to swap two elements of any list. It changes the list so the element with the index * i will be located on index j, and the element with index j, will be located on the index i. @@ -228,7 +272,14 @@ 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 + // todo: complete method implementation + swapHelper(elements,i,j); + } + + private static void swapHelper(List elements, int i, int j) { + T temp = elements.get(i); + elements.set(i, elements.get(j)); + elements.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..6651e81d9 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,12 @@ public BaseEntity(UUID uuid) { this.uuid = uuid; this.createdOn = LocalDateTime.now(); } + + public UUID getUuid() { + return uuid; + } + + public LocalDateTime getCreatedOn() { + return createdOn; + } } diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java index d616e908a..f9ba75514 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java @@ -12,6 +12,7 @@ import java.io.Serializable; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.time.LocalDateTime; @@ -70,7 +71,7 @@ void sourcedClassTypeParameterIsNotBounded() { @SneakyThrows @Order(4) @DisplayName("Sourced class field \"value\" has generic type \"T\"") - void valueFieldIsGeneric() { + void valueFieldIsGeneric() throws NoSuchFieldException { var valueField = Sourced.class.getDeclaredField("value"); var genericType = valueField.getGenericType(); @@ -144,7 +145,7 @@ void converterInterfaceSecondTypeParameterIsCalledR() { @SneakyThrows @Order(11) @DisplayName("Convert method parameter \"obj\" has type \"T\"") - void converterMethodParameterHasTypeT() { + void converterMethodParameterHasTypeT() throws NoSuchMethodException { var convertMethod = Converter.class.getDeclaredMethod("convert", Object.class); var objParam = convertMethod.getParameters()[0]; @@ -155,7 +156,7 @@ void converterMethodParameterHasTypeT() { @SneakyThrows @Order(12) @DisplayName("Convert method return type is \"R\"") - void converterMethodReturnTypeIsR() { + void converterMethodReturnTypeIsR() throws NoSuchMethodException { var convertMethod = Converter.class.getDeclaredMethod("convert", Object.class); assertThat(convertMethod.getGenericReturnType().getTypeName()).isEqualTo(SECOND_TYPE_PARAMETER_NAME); @@ -237,7 +238,7 @@ void maxHolderGetMaxReturnTypeIsT() { @Order(20) @SneakyThrows @DisplayName("MaxHolder put stores argument value when it's greater than max") - void maxHolderPut() { + void maxHolderPut() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { Constructor constructor = MaxHolder.class.getConstructors()[0]; var maxHolder = constructor.newInstance(10); var putMethod = getMethodByName(MaxHolder.class, "put"); @@ -787,7 +788,7 @@ void findMostRecentlyCreatedEntityIsAGenericMethod() { @DisplayName("findMostRecentlyCreatedEntity returns the most recently created entity") @SneakyThrows void findMostRecentlyCreatedEntityReturnsEntityWithMaxCreatedOnValue(List entities, - BaseEntity mostRecentlyCreatedEntity) { + BaseEntity mostRecentlyCreatedEntity) throws InvocationTargetException, IllegalAccessException { var findMostRecentlyCreatedEntityMethod = getMethodByName(CollectionUtil.class, "findMostRecentlyCreatedEntity"); var result = findMostRecentlyCreatedEntityMethod.invoke(null, entities); 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..865e4f723 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,5 +1,7 @@ package com.bobocode.basics; +import java.util.Comparator; +import java.util.HashMap; import java.util.Map; /** @@ -15,7 +17,7 @@ * @author Taras Boychuk */ public class HeterogeneousMaxHolder { - + private final 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 * of this method makes sure that only max value is stored and everything else is ignored. @@ -31,7 +33,14 @@ 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 currentValue = key.cast(maxValues.get(key)); + if (currentValue == null || value.compareTo(currentValue) > 0) { + maxValues.put(key, value); + return currentValue; + } + return value; + } /** * An overloaded method put implements the same logic using a custom comparator. A given comparator is wrapped with * a null-safe comparator, considering null smaller than any non-null object. @@ -45,7 +54,15 @@ 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) { + T currentValue = key.cast(maxValues.get(key)); + if (currentValue == null || comparator.compare(value, currentValue) > 0) { + maxValues.put(key, value); + return currentValue; + } + 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 +71,7 @@ public class HeterogeneousMaxHolder { * @return current max value or null */ // todo: implement a method according to javadoc + public T getMax(Class key){ + return (T) maxValues.get(key); + } } 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..589a22889 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 @@ -29,7 +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..7bba7390e 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,6 @@ 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(x->x*x).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..0279e4369 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 val = () ->"Hello"; + return val; } /** @@ -36,7 +38,8 @@ public static Supplier helloSupplier() { * @return a string predicate */ public static Predicate isEmptyPredicate() { - throw new ExerciseNotCompletedException(); + Predicate val = (x) -> x.isEmpty() ; + return val; } /** @@ -46,7 +49,8 @@ public static Predicate isEmptyPredicate() { * @return function that repeats Strings */ public static BiFunction stringMultiplier() { - throw new ExerciseNotCompletedException(); + BiFunction val = (x,y) -> x.repeat(y); + return val; } /** @@ -56,7 +60,8 @@ public static BiFunction stringMultiplier() { * @return function that converts adds dollar sign */ public static Function toDollarStringFunction() { - throw new ExerciseNotCompletedException(); + Function val = (x) -> "$"+x; + return val; } /** @@ -68,7 +73,8 @@ public static Function toDollarStringFunction() { * @return a string predicate */ public static Predicate lengthInRangePredicate(int min, int max) { - throw new ExerciseNotCompletedException(); + Predicate val = (x)-> min <= x.length() && x.length()< max ; + return val; } /** @@ -77,7 +83,9 @@ public static Predicate lengthInRangePredicate(int min, int max) { * @return int supplier */ public static IntSupplier randomIntSupplier() { - throw new ExerciseNotCompletedException(); + Random random = new Random(); + IntSupplier val = ()-> random.nextInt(); + return val; } @@ -87,7 +95,8 @@ public static IntSupplier randomIntSupplier() { * @return int operation */ public static IntUnaryOperator boundedRandomIntSupplier() { - throw new ExerciseNotCompletedException(); + IntUnaryOperator val = (x)-> new Random(x).nextInt(); + return val; } /** @@ -96,7 +105,8 @@ public static IntUnaryOperator boundedRandomIntSupplier() { * @return square operation */ public static IntUnaryOperator intSquareOperation() { - throw new ExerciseNotCompletedException(); + IntUnaryOperator val = (x) -> x*x; + return val; } /** @@ -105,7 +115,8 @@ public static IntUnaryOperator intSquareOperation() { * @return binary sum operation */ public static LongBinaryOperator longSumOperation() { - throw new ExerciseNotCompletedException(); + LongBinaryOperator val = (x,y) -> x+y; + return val; } /** @@ -114,7 +125,7 @@ public static LongBinaryOperator longSumOperation() { * @return string to int converter */ public static ToIntFunction stringToIntConverter() { - throw new ExerciseNotCompletedException(); + return (x) -> Integer.parseInt(x); } /** @@ -125,7 +136,7 @@ public static ToIntFunction stringToIntConverter() { * @return a function supplier */ public static Supplier nMultiplyFunctionSupplier(int n) { - throw new ExerciseNotCompletedException(); + return ()->(x)->x*n; } /** @@ -134,7 +145,7 @@ public static Supplier nMultiplyFunctionSupplier(int n) { * @return function that composes functions with trim() function */ public static UnaryOperator> composeWithTrimFunction() { - throw new ExerciseNotCompletedException(); + return (y)->(x)->y.apply(x.trim()); } /** @@ -145,7 +156,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 +169,10 @@ public static Supplier runningThreadSupplier(Runnable runnable) { * @return a runnable consumer */ public static Consumer newThreadRunnableConsumer() { - throw new ExerciseNotCompletedException(); + return (runnable -> { + Thread thread = new Thread(runnable); + thread.run(); + }); } /** @@ -164,7 +182,11 @@ public static Consumer newThreadRunnableConsumer() { * @return a function that transforms runnable into a thread supplier */ public static Function> runnableToThreadSupplierFunction() { - throw new ExerciseNotCompletedException(); + return (runnable)->() -> { + Thread thread =new Thread(runnable); + thread.start(); + return thread; + }; } /** @@ -177,7 +199,7 @@ 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 (x,y)->(z)-> y.test(z) ? x.applyAsInt(z):z; } /** @@ -188,7 +210,7 @@ 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(); + return (map,func)-> map.getOrDefault(func,IntUnaryOperator.identity()); } /** @@ -206,7 +228,7 @@ public static BiFunction, String, IntUnaryOperator * @return a comparator instance */ public static > Comparator comparing(Function mapper) { - throw new ExerciseNotCompletedException(); + return (comp1,comp2)->mapper.apply(comp1).compareTo(mapper.apply(comp2)); } /** @@ -226,7 +248,7 @@ public static > Comparator comparing(Funct */ public static > Comparator thenComparing( Comparator comparator, Function mapper) { - throw new ExerciseNotCompletedException(); + return (comp1,comp2)-> comparator.compare(comp1,comp2) != 0 ? comparator.compare(comp1,comp2) : mapper.apply(comp1).compareTo(mapper.apply(comp2)); } /** @@ -235,7 +257,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..093db7b3f 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 @@ -30,7 +36,7 @@ public class CrazyStreams { * @return account with max balance wrapped with optional */ public Optional findRichestPerson() { - throw new ExerciseNotCompletedException(); + return accounts.stream().max(Comparator.comparing(Account::getBalance)); } /** @@ -40,7 +46,7 @@ public Optional findRichestPerson() { * @return a list of accounts */ public List findAccountsByBirthdayMonth(Month birthdayMonth) { - throw new ExerciseNotCompletedException(); + return accounts.stream().filter(account-> account.getBirthday().getMonth() == birthdayMonth).collect(Collectors.toList()); } /** @@ -50,7 +56,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 -> Sex.MALE.equals(account.getSex()))); } /** @@ -60,7 +67,7 @@ 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().substring(account.getEmail().indexOf('@')+1))); } /** @@ -69,7 +76,7 @@ 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 +85,7 @@ 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); } /** @@ -87,7 +94,7 @@ 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 +104,7 @@ 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(x->x.getEmail().substring(x.getEmail().indexOf('@')+1).equals(emailDomain)); } /** @@ -108,7 +115,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)) + .map(Account::getBalance) + .findFirst() + .orElseThrow(()-> new EntityNotFoundException("Cannot find Account by email="+email)); } /** @@ -117,7 +128,7 @@ 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 +139,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 -> account.getEmail(),account -> account.getBalance())); } /** @@ -138,7 +151,10 @@ 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 +164,11 @@ 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 +178,12 @@ 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.mapping(Account::getBalance, + Collectors.reducing(BigDecimal.ZERO,BigDecimal::add) + ))); } /** @@ -168,7 +193,11 @@ 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() + .map(Account::getFirstName) + .flatMapToInt(String::chars) + .mapToObj(c->(char) c) + .collect(Collectors.groupingBy(c->c,Collectors.counting())); } /** @@ -179,7 +208,14 @@ 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() + .filter(account -> account.getFirstName().length() >= nameLengthBound || account.getLastName().length() >= nameLengthBound) + .flatMap(account -> Stream.of(account.getFirstName().toLowerCase(), account.getLastName().toLowerCase())) + .filter(name -> name.length() >= nameLengthBound) + .flatMap(name -> name.chars().mapToObj(c -> (char) c)) + .filter(c -> c >= 'a' && c <= 'z') + .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..228949bf5 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,9 @@ public static Optional optionalOfString(@Nullable String text) { * @param amount money to deposit */ public static void deposit(AccountProvider accountProvider, BigDecimal amount) { - throw new ExerciseNotCompletedException(); + Optional.ofNullable(accountProvider) + .flatMap(AccountProvider::getAccount) + .ifPresent(account->account.setBalance(account.getBalance().add(amount))); } /** @@ -57,7 +57,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 +69,9 @@ 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 Optional.of(accountProvider) + .flatMap(AccountProvider::getAccount) + .orElse(defaultAccount); } /** @@ -80,7 +82,10 @@ public static Account getAccount(AccountProvider accountProvider, Account defaul * @param accountService */ public static void processAccount(AccountProvider accountProvider, AccountService accountService) { - throw new ExerciseNotCompletedException(); + Optional.of(accountProvider) + .flatMap(AccountProvider::getAccount) + .ifPresentOrElse(accountService::processAccount + ,accountService::processWithNoAccount); } /** @@ -91,7 +96,9 @@ public static void processAccount(AccountProvider accountProvider, AccountServic * @return provided or generated account */ public static Account getOrGenerateAccount(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.of(accountProvider) + .flatMap(AccountProvider::getAccount) + .orElseGet(Accounts::generateAccount); } /** @@ -101,7 +108,9 @@ public static Account getOrGenerateAccount(AccountProvider accountProvider) { * @return optional balance */ public static Optional retrieveBalance(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) + .flatMap(AccountProvider::getAccount) + .map(Account::getBalance); } /** @@ -112,7 +121,9 @@ public static Optional retrieveBalance(AccountProvider accountProvid * @return provided account */ public static Account getAccount(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) + .flatMap(AccountProvider::getAccount) + .orElseThrow(()-> new AccountNotFoundException("No Account provided!")); } /** @@ -122,7 +133,9 @@ public static Account getAccount(AccountProvider accountProvider) { * @return optional credit balance */ public static Optional retrieveCreditBalance(CreditAccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) + .flatMap(CreditAccountProvider::getAccount) + .flatMap(CreditAccount::getCreditBalance); } @@ -134,7 +147,10 @@ public static Optional retrieveCreditBalance(CreditAccountProvider a * @return optional gmail account */ public static Optional retrieveAccountGmail(AccountProvider accountProvider) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accountProvider) + .flatMap(AccountProvider::getAccount) + .filter(account -> account.getEmail()!=null && account.getEmail().endsWith("@gmail.com")); + } /** @@ -147,7 +163,10 @@ 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 Optional.ofNullable(accountProvider) + .flatMap(AccountProvider::getAccount) + .or(()->Optional.ofNullable(fallbackProvider).flatMap(AccountProvider::getAccount)) + .orElseThrow(NoSuchElementException::new); } /** @@ -158,7 +177,10 @@ public static Account getAccountWithFallback(AccountProvider accountProvider, Ac * @return account with the highest balance */ public static Account getAccountWithMaxBalance(List accounts) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accounts) + .filter(list -> !list.isEmpty()) + .flatMap(list -> list.stream().max(Comparator.comparing(Account::getBalance))) + .orElseThrow(NoSuchElementException::new); } /** @@ -168,7 +190,11 @@ public static Account getAccountWithMaxBalance(List accounts) { * @return the lowest balance values */ public static OptionalDouble findMinBalanceValue(List accounts) { - throw new ExerciseNotCompletedException(); + return Optional.ofNullable(accounts) + .filter(list->!list.isEmpty()) + .flatMap(list->list.stream().min(Comparator.comparing(Account::getBalance))) + .map(account ->OptionalDouble.of(account.getBalance().doubleValue())) + .orElseGet(OptionalDouble::empty); } /** @@ -178,7 +204,10 @@ public static OptionalDouble findMinBalanceValue(List accounts) { * @param accountService */ public static void processAccountWithMaxBalance(List accounts, AccountService accountService) { - throw new ExerciseNotCompletedException(); + Optional.ofNullable(accounts) + .filter(list->!list.isEmpty()) + .flatMap(list->list.stream().max(Comparator.comparing(Account::getBalance))) + .ifPresent(accountService::processAccount); } /** @@ -188,7 +217,14 @@ public static void processAccountWithMaxBalance(List accounts, AccountS * @return total credit balance */ public static double calculateTotalCreditBalance(List accounts) { - throw new ExerciseNotCompletedException(); + + return Optional.ofNullable(accounts) + .stream() + .flatMap(List::stream) + .map(CreditAccount::getCreditBalance) + .flatMap(Optional::stream) + .mapToDouble(BigDecimal::doubleValue) + .sum(); } } 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..741d59127 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 @@ -1,10 +1,13 @@ package com.bobocode.fp; import com.bobocode.util.ExerciseNotCompletedException; +import com.google.common.math.IntMath; +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 +33,8 @@ 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 + // todo: create an infinite stream of ints, then filter prime numbs + return IntStream.iterate(0,i->i+1).filter(IntMath::isPrime); } /** @@ -40,7 +44,8 @@ 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 + // todo: use the prev to generate a stream method but limit its size + return stream().limit(size); } /** @@ -51,7 +56,8 @@ 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 + // todo: use prev method and calculate the sum + return stream().limit(n).sum(); } @@ -61,7 +67,8 @@ 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 + // todo: collect prime numbers into the list + return stream().limit(n).boxed().collect(Collectors.toList()); } /** @@ -71,7 +78,8 @@ 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 + // todo: find an element in the stream by index and process it + stream().skip(idx).findFirst().ifPresent(consumer); } /** @@ -85,6 +93,10 @@ 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 + // todo: group n prime numbers by the amount of digits + return stream() + .limit(n) + .boxed() + .collect(Collectors.groupingBy(num -> String.valueOf(num).length())); } } 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..0b5768123 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,71 @@ public class Account { private Sex sex; private LocalDate creationDate; private BigDecimal balance = BigDecimal.ZERO; + + public BigDecimal getBalance() { + return balance; + } + + public String getLastName() { + return lastName; + } + + public String getFirstName() { + return firstName; + } + + public String getEmail() { + return email; + } + + public LocalDate getBirthday() { + return birthday; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public Sex getSex() { + return sex; + } + + public Long getId() { + return id; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public void setCreationDate(LocalDate creationDate) { + this.creationDate = creationDate; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public void setId(Long id) { + this.id = id; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + }