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
index 35d925636..181b9990e 100644
--- a/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java
+++ b/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java
@@ -1,6 +1,7 @@
package com.bobocode.intro;
-import com.bobocode.util.ExerciseNotCompletedException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
/**
* Welcome! This is an introduction exercise that will show you a simple example of Bobocode exercises.
@@ -23,8 +24,7 @@ public class ExerciseIntroduction {
* @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();
+ return "The key to efficient learning is practice!";
}
/**
@@ -39,7 +39,6 @@ public String getWelcomeMessage() {
* @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();
+ return Base64.getEncoder().encodeToString(message.getBytes(StandardCharsets.UTF_8));
}
}
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..9893166a8 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,13 +9,13 @@
*/
public class BoxDemoApp {
public static void main(String[] args) {
- Box intBox = new Box(123);
- Box intBox2 = new Box(321);
- System.out.println((int) intBox.getValue() + (int) intBox2.getValue());
+ var intBox = new Box<>(123);
+ var intBox2 = new Box<>(321);
+ System.out.println(intBox.getValue() + 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());
+ System.out.println(intBox.getValue() + 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..d41d0a3af 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,10 @@
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;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated
@@ -33,8 +33,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 +45,11 @@ 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;
}
/**
@@ -59,8 +59,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 value);
}
/**
@@ -70,10 +70,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 +82,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) {
+ this.max = max.compareTo(val) < 0 ? val : max;
}
- public Object getMax() {
+ public T getMax() {
return max;
}
}
@@ -97,8 +97,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 & Serializable> { // todo: make it generic
+ void process(T obj);
}
/**
@@ -108,10 +108,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 +120,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 +133,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
+ interface ComparableCollection extends Collection, Comparable>{
+ @Override
+ default int compareTo(Collection> o) {
+ return Integer.compare(this.size(), o.size());
+ }
}
/**
@@ -147,7 +151,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 +164,8 @@ 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 extends BaseEntity> entities) {
+ return entities.stream().anyMatch(entity -> entity.getUuid() == null);
}
/**
@@ -173,8 +177,8 @@ 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 extends BaseEntity> entities, Predicate super BaseEntity> validationPredicate) {
+ return entities.stream().allMatch(validationPredicate);
}
/**
@@ -187,8 +191,8 @@ 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) {
+ return entities.stream().filter(entity -> entity.getUuid().equals(targetEntity.getUuid())).count() > 1;
}
/**
@@ -201,7 +205,18 @@ 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;
+ Iterator iterator = elements.iterator();
+ while (iterator.hasNext()) {
+ var element = iterator.next();
+ if (max == null) { max = element; }
+ if (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 +230,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){
+ if (entities == null || entities.isEmpty()) throw new NoSuchElementException();
+ return (T) findMax(entities.stream().collect(Collectors.toUnmodifiableSet()), CREATED_ON_COMPARATOR).get();
+ }
/**
* 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 +246,11 @@ 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
+ var elementI = elements.get(i);
+ var elementJ = elements.get(j);
+ final List l = elements;
+ l.set(i, elementJ);
+ l.set(j, elementI);
}
}
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..b300f7924 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;
/**
@@ -16,6 +18,8 @@
*/
public class HeterogeneousMaxHolder {
+ private final Map, Object> map = 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 +35,17 @@ 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) {
+ if (!map.containsKey(key)) {
+ map.put(key, value);
+ return null;
+ }
+ var storedValue = (T) map.get(key);
+ if (value.compareTo(storedValue) > 0) {
+ map.put(key, value);
+ return storedValue;
+ } else 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 +59,17 @@ 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 super T> comparator) {
+ if (!map.containsKey(key)) {
+ map.put(key, value);
+ return null;
+ }
+ var storedValue = (T) map.get(key);
+ if (comparator.compare(value, storedValue) > 0) {
+ map.put(key, value);
+ return storedValue;
+ } 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 +78,7 @@ public class HeterogeneousMaxHolder {
* @return current max value or null
*/
// todo: implement a method according to javadoc
+ public T getMax(Class key) {
+ return (T) map.get(key);
+ }
}
diff --git a/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Exercise.java b/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Exercise.java
new file mode 100644
index 000000000..7c3a45e78
--- /dev/null
+++ b/1-0-java-basics/1-5-0-hello-annotations/src/main/java/com/bobocode/basics/Exercise.java
@@ -0,0 +1,14 @@
+package com.bobocode.basics;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Exercise {
+ String name() default "hello-annotation-basic";
+ String value() default "";
+ Level complexityLevel() default Level.BASIC;
+}
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
index 4dc8c4b22..0f8fff9a8 100644
--- 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
@@ -13,5 +13,7 @@
*
* @author Taras Boychuk
*/
-public class HelloAnnotationsExercise { // todo: mark class with the annotation according to the javadoc
+@Exercise(value = "hello-annotation-basic", complexityLevel = Level.BASIC)
+public class HelloAnnotationsExercise {
+
}
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
index b01a4acfb..68a942eeb 100644
--- 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
@@ -1,5 +1,8 @@
package com.bobobode.cs;
+import lombok.Getter;
+import lombok.Setter;
+
/**
* 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}
@@ -9,5 +12,20 @@
* @author Taras Boychuk
*/
public class Node {
- // todo:
+ @Getter
+ private T value;
+
+ @Getter
+ @Setter
+ private Node next;
+
+ public Node(T value) {
+ this.value = value;
+ }
+
+ public Node(T value, Node next) {
+ this.value = value;
+ this.next = next;
+ }
+
}
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
index 5321aa53a..63867492d 100644
--- 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
@@ -1,6 +1,7 @@
package com.bobobode.cs;
-import com.bobocode.util.ExerciseNotCompletedException;
+import java.util.ArrayList;
+import java.util.List;
/**
* A class that consists of static methods only and provides util methods for {@link Node}.
@@ -11,6 +12,7 @@
* @author Taras Boychuk
*/
public class Nodes {
+
private Nodes() {
}
@@ -22,7 +24,7 @@ private Nodes() {
* @return a new instance of {@link Node}
*/
public static Node create(T element) {
- throw new ExerciseNotCompletedException(); // todo:
+ return new Node<>(element);
}
/**
@@ -33,7 +35,8 @@ public static Node create(T element) {
* @param a genetic type
*/
public static void link(Node first, Node second) {
- throw new ExerciseNotCompletedException(); // todo:
+ if (first == null || second == null) { return; }
+ first.setNext(second);
}
/**
@@ -46,7 +49,7 @@ public static void link(Node first, Node second) {
* @return a reference to a first node created based on firstElement
*/
public static Node pairOf(T firstElement, T secondElement) {
- throw new ExerciseNotCompletedException(); // todo:
+ return new Node<>(firstElement, new Node<>(secondElement));
}
/**
@@ -60,7 +63,11 @@ public static Node pairOf(T firstElement, T secondElement) {
* @return a reference to the first node
*/
public static Node closedPairOf(T firstElement, T secondElement) {
- throw new ExerciseNotCompletedException(); // todo:
+ var firstNode = new Node<>(firstElement);
+ var secondNode = new Node<>(secondElement);
+ firstNode.setNext(secondNode);
+ secondNode.setNext(firstNode);
+ return firstNode;
}
/**
@@ -72,7 +79,20 @@ public static Node closedPairOf(T firstElement, T secondElement) {
* @return a reference to the first element of the chain
*/
public static Node chainOf(T... elements) {
- throw new ExerciseNotCompletedException(); // todo:
+ List elementsList = List.of(elements);
+ List nodes = new ArrayList<>(elementsList.size());
+ for (int i = 0; i <= elementsList.size() - 1; i++) {
+ if (i == elementsList.size() - 1) {
+ nodes.add(new Node<>(elementsList.get(i)));
+ } else {
+ var firstNode = i != 0 ? nodes.getLast() : new Node<>(elementsList.get(i));
+ var nextNode = new Node<>(elementsList.get(i + 1));
+ firstNode.setNext(nextNode);
+ nodes.add(firstNode);
+ nodes.add(nextNode);
+ }
+ }
+ return nodes.getFirst();
}
/**
@@ -85,6 +105,19 @@ public static Node chainOf(T... elements) {
* @return a reference to the first element of the chain
*/
public static Node circleOf(T... elements) {
- throw new ExerciseNotCompletedException(); // todo:
+ List elementsList = List.of(elements);
+ List nodes = new ArrayList<>(elementsList.size());
+ for (int i = 0; i <= elementsList.size() - 1; i++) {
+ if (i == elementsList.size() - 1) {
+ nodes.getLast().setNext(nodes.getFirst());
+ } else {
+ var firstNode = i != 0 ? nodes.getLast() : new Node<>(elementsList.get(i));
+ var nextNode = new Node<>(elementsList.get(i + 1));
+ firstNode.setNext(nextNode);
+ nodes.add(firstNode);
+ nodes.add(nextNode);
+ }
+ }
+ return nodes.getFirst();
}
}
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
index 05b0c724d..29a17d2fb 100644
--- 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
@@ -1,7 +1,13 @@
package com.bobocode.cs;
import com.bobocode.cs.exception.EmptyStackException;
-import com.bobocode.util.ExerciseNotCompletedException;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
/**
* {@link LinkedStack} is a stack implementation that is based on singly linked generic nodes.
@@ -16,6 +22,12 @@
*/
public class LinkedStack implements Stack {
+ private Node head;
+
+ private int size;
+
+ public LinkedStack() {}
+
/**
* This method creates a stack of provided elements
*
@@ -24,7 +36,9 @@ public class LinkedStack implements Stack {
* @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
+ LinkedStack linkedStack = new LinkedStack<>();
+ Stream.of(elements).forEach(linkedStack::push);
+ return linkedStack;
}
/**
@@ -35,7 +49,13 @@ public static LinkedStack of(T... elements) {
*/
@Override
public void push(T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Objects.requireNonNull(element);
+ Node newNode = Node.valueOf(element);
+ if (head != null) {
+ newNode.next = head;
+ }
+ head = newNode;
+ size++;
}
/**
@@ -47,7 +67,14 @@ public void push(T element) {
*/
@Override
public T pop() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ if (head != null) {
+ size--;
+ var element = head.getValue();
+ this.head = head.next;
+ return element;
+ } else {
+ throw new EmptyStackException();
+ }
}
/**
@@ -57,7 +84,7 @@ public T pop() {
*/
@Override
public int size() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return size;
}
/**
@@ -67,7 +94,28 @@ public int size() {
*/
@Override
public boolean isEmpty() {
- throw new ExerciseNotCompletedException(); // todo: implement this method;
- }
+ return head == null; }
+
+ private static class Node {
+ @Getter
+ private T value;
+
+ @Getter
+ @Setter
+ private Node next;
+
+ private Node(T value) {
+ this.value = value;
+ }
+
+ private Node(T value, Node next) {
+ this.value = value;
+ this.next = next;
+ }
+
+ private static Node valueOf(T element) {
+ return new Node<>(element);
+ }
+ }
}
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
index 7b4a79667..5e8a8b1ea 100644
--- 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
@@ -16,13 +16,26 @@
*/
public class LinkedQueue implements Queue {
+ private Node head;
+
+ private Node tail;
+
+ private int size;
+
/**
* 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
+ Node newNode = Node.valueOf(element);
+ if (head == null) {
+ head = tail = newNode;
+ } else {
+ tail.next = newNode;
+ tail = newNode;
+ }
+ size++;
}
/**
@@ -31,7 +44,17 @@ public void add(T element) {
* @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
+ if (head != null) {
+ T element = head.element;
+ head = head.next;
+ if (head == null) {
+ tail = null;
+ }
+ size--;
+ return element;
+ } else {
+ return null;
+ }
}
/**
@@ -40,7 +63,7 @@ public T poll() {
* @return an integer value that is a size of queue
*/
public int size() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return size;
}
/**
@@ -49,6 +72,21 @@ public int size() {
* @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
+ return head == null;
+ }
+
+ private static final class Node {
+
+ private final T element;
+
+ private Node next;
+
+ private static Node valueOf(T element) {
+ return new Node<>(element);
+ }
+
+ private Node(T element) {
+ this.element = element;
+ }
}
}
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
index 502fefbdf..0982304bc 100644
--- 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
@@ -3,6 +3,10 @@
import com.bobocode.util.ExerciseNotCompletedException;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.stream.Stream;
+
/**
* {@link LinkedList} is a list implementation that is based on singly linked generic nodes. A node is implemented as
* inner static class {@link Node}.
@@ -16,6 +20,12 @@
*/
public class LinkedList implements List {
+ private Node first;
+
+ private Node last;
+
+ private int size;
+
/**
* This method creates a list of provided elements
*
@@ -24,7 +34,9 @@ public class LinkedList implements List {
* @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
+ LinkedList linkedList = new LinkedList<>();
+ Stream.of(elements).forEach(linkedList::add);
+ return linkedList;
}
/**
@@ -34,7 +46,14 @@ public static LinkedList of(T... elements) {
*/
@Override
public void add(T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Node newNode = new Node<>(element);
+ if (size == 0) {
+ first = last = newNode;
+ } else {
+ last.next = newNode;
+ last = newNode;
+ }
+ size++;
}
/**
@@ -46,7 +65,51 @@ public void add(T element) {
*/
@Override
public void add(int index, T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Node newNode = Node.valueOf(element);
+ if (index == 0) {
+ addAsHead(newNode);
+ } else if (index == size) {
+ addAsTail(newNode);
+ } else {
+ add(index, newNode);
+ }
+ size++;
+ }
+
+ private void addAsHead(Node newNode) {
+ newNode.next = first;
+ first = newNode;
+ if (first.next == null) {
+ last = first;
+ }
+ }
+
+ private void addAsTail(Node newNode) {
+ last.next = newNode;
+ last = newNode;
+ }
+
+ private void add(int index, Node newNode) {
+ Node node = findNodeByIndex(index - 1);
+ newNode.next = node.next;
+ node.next = newNode;
+ }
+
+ private Node findNodeByIndex(int index) {
+ Objects.checkIndex(index, size);
+ if (index == size - 1) {
+ return last;
+ } else {
+ return nodeAt(index);
+ }
+ }
+
+ private Node nodeAt(int index) {
+ Node currentNode = first;
+ for (int i = 0; i < index; i++) {
+ currentNode = currentNode.next;
+ }
+ return currentNode;
}
/**
@@ -58,7 +121,8 @@ public void add(int index, T element) {
*/
@Override
public void set(int index, T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Node node = findNodeByIndex(index);
+ node.value = element;
}
/**
@@ -70,7 +134,8 @@ public void set(int index, T element) {
*/
@Override
public T get(int index) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Node node = findNodeByIndex(index);
+ return node.value;
}
/**
@@ -81,7 +146,8 @@ public T get(int index) {
*/
@Override
public T getFirst() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ checkElementsExist();
+ return first.value;
}
/**
@@ -92,7 +158,14 @@ public T getFirst() {
*/
@Override
public T getLast() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ checkElementsExist();
+ return last.value;
+ }
+
+ private void checkElementsExist() {
+ if (first == null) {
+ throw new NoSuchElementException();
+ }
}
/**
@@ -104,7 +177,27 @@ public T getLast() {
*/
@Override
public T remove(int index) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ T deletedElement;
+ if (index == 0 && !isEmpty()) {
+ deletedElement = first.value;
+ removeHead();
+ } else {
+ Node previousNode = findNodeByIndex(index - 1);
+ deletedElement = previousNode.next.value;
+ previousNode.next = previousNode.next.next;
+ if (index == size - 1) {
+ last = previousNode;
+ }
+ }
+ size--;
+ return deletedElement;
+ }
+
+ private void removeHead() {
+ first = first.next;
+ if (first == null) {
+ last = null;
+ }
}
@@ -115,7 +208,14 @@ public T remove(int index) {
*/
@Override
public boolean contains(T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Node currentNode = first;
+ while (currentNode != null) {
+ if (currentNode.value.equals(element)) {
+ return true;
+ }
+ currentNode = currentNode.next;
+ }
+ return false;
}
/**
@@ -125,7 +225,7 @@ public boolean contains(T element) {
*/
@Override
public boolean isEmpty() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return first == null;
}
/**
@@ -135,7 +235,7 @@ public boolean isEmpty() {
*/
@Override
public int size() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return size;
}
/**
@@ -143,6 +243,22 @@ public int size() {
*/
@Override
public void clear() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ first = last = null;
+ size = 0;
+ }
+
+ private static class Node {
+
+ private T value;
+
+ private Node next;
+
+ private Node(T value) {
+ this.value = value;
+ }
+
+ private static Node valueOf(T value) {
+ return new Node<>(value);
+ }
}
}
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
index 384ca81e5..8e03f5bdb 100644
--- 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
@@ -1,6 +1,8 @@
package com.bobocode.cs;
-import com.bobocode.util.ExerciseNotCompletedException;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import java.util.Objects;
/**
* {@link ArrayList} is an implementation of {@link List} interface. This resizable data structure
@@ -13,6 +15,12 @@
*/
public class ArrayList implements List {
+ private static final int DEFAULT_CAPACITY = 5;
+
+ private Object[] elementData;
+
+ private int size;
+
/**
* This constructor creates an instance of {@link ArrayList} with a specific capacity of an array inside.
*
@@ -20,7 +28,10 @@ public class ArrayList implements List {
* @throws IllegalArgumentException – if the specified initial capacity is negative or 0.
*/
public ArrayList(int initCapacity) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ if (initCapacity <= 0) {
+ throw new IllegalArgumentException();
+ }
+ elementData = new Object[initCapacity];
}
/**
@@ -28,7 +39,7 @@ public ArrayList(int initCapacity) {
* A default size of inner array is 5;
*/
public ArrayList() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ this(DEFAULT_CAPACITY);
}
/**
@@ -38,7 +49,10 @@ public ArrayList() {
* @return new instance
*/
public static List of(T... elements) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ ArrayList list = new ArrayList<>(elements.length);
+ list.elementData = Arrays.copyOf(elements, elements.length);
+ list.size = elements.length;
+ return list;
}
/**
@@ -48,7 +62,15 @@ public static List of(T... elements) {
*/
@Override
public void add(T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ increaseDataArrayIfFull();
+ elementData[size] = element;
+ size++;
+ }
+
+ private void increaseDataArrayIfFull() {
+ if (elementData.length == size) {
+ elementData = Arrays.copyOf(elementData, size * 2);
+ }
}
/**
@@ -59,7 +81,10 @@ public void add(T element) {
*/
@Override
public void add(int index, T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ increaseDataArrayIfFull();
+ System.arraycopy(elementData, index, elementData, index + 1, size - index);
+ elementData[index] = element;
+ size++;
}
/**
@@ -71,7 +96,8 @@ public void add(int index, T element) {
*/
@Override
public T get(int index) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Objects.checkIndex(index, size);
+ return (T) elementData[index];
}
/**
@@ -82,7 +108,10 @@ public T get(int index) {
*/
@Override
public T getFirst() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ if (isEmpty()) {
+ throw new NoSuchElementException();
+ }
+ return (T) elementData[0];
}
/**
@@ -93,7 +122,10 @@ public T getFirst() {
*/
@Override
public T getLast() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ if (isEmpty()) {
+ throw new NoSuchElementException();
+ }
+ return (T) elementData[size - 1];
}
/**
@@ -105,7 +137,8 @@ public T getLast() {
*/
@Override
public void set(int index, T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Objects.checkIndex(index, size);
+ elementData[index] = element;
}
/**
@@ -117,7 +150,14 @@ public void set(int index, T element) {
*/
@Override
public T remove(int index) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ Objects.checkIndex(index, size);
+ T deletedElement = (T) elementData[index];
+ if (index < size - 1) {
+ System.arraycopy(elementData, index + 1, elementData, index, size - index - 1);
+ }
+ elementData[size - 1] = null;
+ size--;
+ return deletedElement;
}
/**
@@ -128,7 +168,12 @@ public T remove(int index) {
*/
@Override
public boolean contains(T element) {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ for (int i = 0; i < size; i++) {
+ if (elementData[i].equals(element)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -138,7 +183,7 @@ public boolean contains(T element) {
*/
@Override
public boolean isEmpty() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return size == 0;
}
/**
@@ -146,7 +191,7 @@ public boolean isEmpty() {
*/
@Override
public int size() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ return size;
}
/**
@@ -154,6 +199,7 @@ public int size() {
*/
@Override
public void clear() {
- throw new ExerciseNotCompletedException(); // todo: implement this method
+ elementData = new Object[DEFAULT_CAPACITY];
+ size = 0;
}
}
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
index a4e394b0b..2ac02f8a7 100644
--- 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
@@ -2,7 +2,9 @@
import com.bobocode.util.ExerciseNotCompletedException;
+import java.util.Objects;
import java.util.function.Consumer;
+import java.util.stream.Stream;
/**
* {@link RecursiveBinarySearchTree} is an implementation of a {@link BinarySearchTree} that is based on a linked nodes
@@ -18,32 +20,126 @@
*/
public class RecursiveBinarySearchTree> implements BinarySearchTree {
+ private static class Node {
+
+ T element;
+
+ Node left;
+
+ Node right;
+
+ private Node(T element) {
+ this.element = element;
+ }
+
+ private static Node valueOf(T element) {
+ return new Node<>(element);
+ }
+ }
+
+ private Node root;
+
+ private int size = 0;
+
public static > RecursiveBinarySearchTree of(T... elements) {
- throw new ExerciseNotCompletedException();
+ RecursiveBinarySearchTree bst = new RecursiveBinarySearchTree<>();
+ Stream.of(elements).forEach(bst::insert);
+ return bst;
}
@Override
public boolean insert(T element) {
- throw new ExerciseNotCompletedException();
+ Objects.requireNonNull(element);
+ boolean isInserted = insertElement(element);
+ if (isInserted) {
+ size++;
+ }
+ return isInserted;
+ }
+
+ boolean insertElement(T element) {
+ if (root == null) {
+ root = Node.valueOf(element);
+ return true;
+ } else {
+ return insertIntoSubTree(root, element);
+ }
}
@Override
public boolean contains(T element) {
- throw new ExerciseNotCompletedException();
+ Objects.requireNonNull(element);
+ return findChildNodeByElement(root, element) != null;
+ }
+
+ private boolean insertIntoSubTree(Node subTreeRoot, T element) {
+ if (subTreeRoot.element.compareTo(element) > 0) {
+ return insertIntoLeftSubtree(subTreeRoot, element);
+ } else if (subTreeRoot.element.compareTo(element) < 0) {
+ return insertIntoRightSubtree(subTreeRoot, element);
+ } else {
+ return false;
+ }
+ }
+
+ private boolean insertIntoLeftSubtree(Node node, T element) {
+ if (node.left != null) {
+ return insertIntoSubTree(node.left, element);
+ } else {
+ node.left = Node.valueOf(element);
+ return true;
+ }
+ }
+
+ private boolean insertIntoRightSubtree(Node node, T element) {
+ if (node.right != null) {
+ return insertIntoSubTree(node.right, element);
+ } else {
+ node.right = Node.valueOf(element);
+ return true;
+ }
}
@Override
public int size() {
- throw new ExerciseNotCompletedException();
+ return size;
+ }
+
+ private Node findChildNodeByElement(Node node, T element) {
+ if (node == null) {
+ return null;
+ } else if (node.element.compareTo(element) > 0) {
+ return findChildNodeByElement(node.left, element);
+ } else if (node.element.compareTo(element) < 0) {
+ return findChildNodeByElement(node.right, element);
+ } else {
+ return node;
+ }
}
@Override
public int depth() {
- throw new ExerciseNotCompletedException();
+ return root != null ? depth(root) - 1 : 0;
+ }
+
+ private int depth(Node node) {
+ if (node == null) {
+ return 0;
+ } else {
+ return 1 + Math.max(depth(node.left), depth(node.right));
+ }
}
@Override
public void inOrderTraversal(Consumer consumer) {
- throw new ExerciseNotCompletedException();
+ inOrderTraversal(root, consumer);
+ }
+
+ private void inOrderTraversal(Node node, Consumer consumer) {
+ if (node != null) {
+ inOrderTraversal(node.left, consumer);
+ consumer.accept(node.element);
+ inOrderTraversal(node.right, consumer);
+ }
}
}
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
index ade9cea4d..154b0bad9 100644
--- 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
@@ -1,6 +1,9 @@
package com.bobocode.cs;
import com.bobocode.util.ExerciseNotCompletedException;
+import lombok.ToString;
+
+import static java.util.Objects.requireNonNull;
/**
* {@link HashTable} is a simple Hashtable-based implementation of {@link Map} interface with some additional methods.
@@ -28,6 +31,23 @@
*/
public class HashTable implements Map {
+ private static final int DEFAULT_CAPACITY = 8;
+
+ private static final float RESIZE_THRESHOLD = 1.0f;
+
+ private Node[] table;
+
+ private int size;
+
+ @SuppressWarnings("unchecked")
+ public HashTable(int initialCapacity) {
+ verifyCapacity(initialCapacity);
+ this.table = new Node[initialCapacity];
+ }
+
+ public HashTable() {
+ this(DEFAULT_CAPACITY);
+ }
/**
* 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
@@ -43,7 +63,8 @@ public class HashTable implements Map {
* @return array index of the given key
*/
public static int calculateIndex(Object key, int tableCapacity) {
- throw new ExerciseNotCompletedException(); // todo:
+ var hash = key.hashCode() ^ (key.hashCode() >> 16);
+ return hash & (tableCapacity - 1);
}
/**
@@ -59,7 +80,40 @@ public static int calculateIndex(Object key, int tableCapacity) {
*/
@Override
public V put(K key, V value) {
- throw new ExerciseNotCompletedException(); // todo:
+ resizeIfNeeded();
+ return putOnTable(table, key, value);
+ }
+
+ private void resizeIfNeeded() {
+ if (size / (float) table.length > RESIZE_THRESHOLD) {
+ resizeTable(2 * table.length);
+ }
+ }
+
+ private V putOnTable(Node[] table, K key, V value) {
+ var newNode = new Node<>(requireNonNull(key), requireNonNull(value));
+ var index = calculateIndex(key, table.length);
+ if (table[index] == null) { // add new head key
+ table[index] = newNode;
+ } else {
+ var current = table[index];
+ while (current.next != null) { // iterate linked list to new key
+ if (current.key.equals(key)) {
+ var prevValue = current.value;
+ current.value = value;
+ return prevValue;
+ }
+ current = current.next;
+ }
+ if (current.key.equals(key)) {
+ var prevValue = current.value;
+ current.value = value;
+ return prevValue;
+ }
+ current.next = newNode; // attach new key to the end of the list
+ }
+ size++;
+ return null;
}
/**
@@ -71,7 +125,15 @@ public V put(K key, V value) {
*/
@Override
public V get(K key) {
- throw new ExerciseNotCompletedException(); // todo:
+ var index = calculateIndex(requireNonNull(key), table.length);
+ var current = table[index];
+ while (current != null) {
+ if (current.key.equals(key)) {
+ return current.value;
+ }
+ current = current.next;
+ }
+ return null;
}
/**
@@ -82,7 +144,7 @@ public V get(K key) {
*/
@Override
public boolean containsKey(K key) {
- throw new ExerciseNotCompletedException(); // todo:
+ return get(key) != null;
}
/**
@@ -93,7 +155,16 @@ public boolean containsKey(K key) {
*/
@Override
public boolean containsValue(V value) {
- throw new ExerciseNotCompletedException(); // todo:
+ for (var head : table) {
+ var current = head;
+ while (current != null) {
+ if (current.value.equals(value)) {
+ return true;
+ }
+ current = current.next;
+ }
+ }
+ return false;
}
/**
@@ -103,7 +174,7 @@ public boolean containsValue(V value) {
*/
@Override
public int size() {
- throw new ExerciseNotCompletedException(); // todo:
+ return size;
}
/**
@@ -113,7 +184,7 @@ public int size() {
*/
@Override
public boolean isEmpty() {
- throw new ExerciseNotCompletedException(); // todo:
+ return size == 0;
}
/**
@@ -124,7 +195,26 @@ public boolean isEmpty() {
*/
@Override
public V remove(K key) {
- throw new ExerciseNotCompletedException(); // todo:
+ var index = calculateIndex(requireNonNull(key), table.length);
+ var current = table[index];
+ if (current != null) {
+ if (current.key.equals(key)) {
+ var value = current.value;
+ table[index] = current.next;
+ size--;
+ return value;
+ }
+ while (current.next != null) {
+ if (current.next.key.equals(key)) {
+ var value = current.next.value;
+ current.next = current.next.next;
+ size--;
+ return value;
+ }
+ current = current.next;
+ }
+ }
+ return null;
}
/**
@@ -150,7 +240,22 @@ public V remove(K key) {
*/
@Override
public String toString() {
- throw new ExerciseNotCompletedException(); // todo:
+ var stringBuilder = new StringBuilder();
+ var n = table.length;
+ for (int i = 0; i < n; i++) { // iterate array
+ stringBuilder.append(i).append(": ");
+ var current = table[i];
+ if (current != null) {
+ while (current.next != null) { // iterate each linked list
+ stringBuilder.append(current.key).append("=").append(current.value).append(" -> ");
+ current = current.next;
+ }
+ stringBuilder.append(current.key).append("=").append(current.value).append("\n");
+ } else {
+ stringBuilder.append("\n");
+ }
+ }
+ return stringBuilder.toString();
}
/**
@@ -167,6 +272,37 @@ public String toString() {
* @param newCapacity a size of the new underlying array
*/
public void resizeTable(int newCapacity) {
- throw new ExerciseNotCompletedException(); // todo:
+ verifyCapacity(newCapacity);
+ @SuppressWarnings("unchecked") Node[] newTable = new Node[newCapacity];
+ size = 0;
+ for (var head : table) {
+ var current = head;
+ while (current != null) {
+ putOnTable(newTable, current.key, current.value);
+ current = current.next;
+ }
+ }
+ table = newTable;
+ }
+
+ private void verifyCapacity(int capacity) {
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("Capacity (table array size) must be positive");
+ }
+ }
+
+ @ToString(exclude = "next")
+ public static class Node {
+
+ T key;
+
+ V value;
+
+ Node next;
+
+ public Node(T key, V value) {
+ this.key = key;
+ this.value = value;
+ }
}
}
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
index 6370a3638..f518af31f 100644
--- 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
@@ -2,6 +2,17 @@
import com.bobocode.util.ExerciseNotCompletedException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.joining;
+
/**
* {@link FileReaders} provides an API that allow to read whole file into a {@link String} by file name.
*/
@@ -14,6 +25,13 @@ public class FileReaders {
* @return string that holds whole file content
*/
public static String readWholeFile(String fileName) {
- throw new ExerciseNotCompletedException(); //todo
+ try {
+ var fileUrl = FileReaders.class.getClassLoader().getResource(fileName);
+ var filePath = Paths.get(fileUrl.toURI());
+ return Files.readString(filePath);
+ } catch (URISyntaxException | IOException e) {
+ throw new RuntimeException(e);
+ }
+
}
}
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
index 56b4aa596..ea4e5b9fc 100644
--- 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
@@ -1,12 +1,88 @@
package com.bobocode.se;
import com.bobocode.util.ExerciseNotCompletedException;
+import lombok.Getter;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.counting;
+import static java.util.stream.Collectors.groupingBy;
/**
* {@link FileStats} provides an API that allow to get character statistic based on text file. All whitespace characters
* are ignored.
*/
public class FileStats {
+
+ private final Map characterCountMap;
+ /**
+ * -- GETTER --
+ * Returns a character that appeared most often in the text.
+ *
+ * @return the most frequently appeared character
+ */
+ @Getter
+ private final char mostPopularCharacter;
+
+ private FileStats(String fileName) {
+ Path filePath = getFilePath(fileName);
+ characterCountMap = computeCharacterMap(filePath);
+ mostPopularCharacter = findMostPopularCharacter(characterCountMap);
+ }
+
+ private Path getFilePath(String fileName) {
+ Objects.requireNonNull(fileName);
+ URL fileUrl = getFileUrl(fileName);
+ try {
+ return Paths.get(fileUrl.toURI());
+ } catch (URISyntaxException e) {
+ throw new FileStatsException("Wrong file path", e);
+ }
+ }
+
+ private Map computeCharacterMap(Path filePath) {
+ try (var lines = Files.lines(filePath)) {
+ return collectCharactersToCountMap(lines);
+ } catch (IOException e) {
+ throw new FileStatsException("Cannot read the file", e);
+ }
+ }
+
+ private Map collectCharactersToCountMap(Stream linesStream) {
+ return linesStream
+ .flatMapToInt(String::chars)
+ .filter(a -> a != 32) // filter whitespace
+ .mapToObj(c -> (char) c)
+ .collect(groupingBy(identity(), counting()));
+ }
+
+
+ private URL getFileUrl(String fileName) {
+ URL fileUrl = getClass().getClassLoader().getResource(fileName);
+ if (fileUrl == null) {
+ throw new FileStatsException("Wrong file path");
+ }
+ return fileUrl;
+ }
+
+ private char findMostPopularCharacter(Map characterCountMap) {
+ return characterCountMap.entrySet()
+ .stream()
+ .max(Map.Entry.comparingByValue())
+ .get()
+ .getKey();
+ }
+
/**
* Creates a new immutable {@link FileStats} objects using data from text file received as a parameter.
*
@@ -14,7 +90,7 @@ public class FileStats {
* @return new FileStats object created from text file
*/
public static FileStats from(String fileName) {
- throw new ExerciseNotCompletedException(); //todo
+ return new FileStats(fileName);
}
/**
@@ -24,16 +100,7 @@ public static FileStats from(String fileName) {
* @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
+ return characterCountMap.get(character).intValue();
}
/**
@@ -43,6 +110,6 @@ public char getMostPopularCharacter() {
* @return {@code true} if this character has appeared in the text, and {@code false} otherwise
*/
public boolean containsCharacter(char character) {
- throw new ExerciseNotCompletedException(); //todo
+ return characterCountMap.containsKey(character);
}
}
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
index e213d3f26..80652ac29 100644
--- 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
@@ -21,7 +21,7 @@ public class CrazyRegex {
* @return a pattern that looks for the word "Curiosity"
*/
public Pattern findSpecificWord() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("Curiosity");
}
/**
@@ -30,7 +30,7 @@ public Pattern findSpecificWord() {
* @return a pattern that looks for the first word in text
*/
public Pattern findFirstWord() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("^\\w+");
}
/**
@@ -39,7 +39,7 @@ public Pattern findFirstWord() {
* @return a pattern that looks for the last word in text
*/
public Pattern findLastWord() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\w+$");
}
/**
@@ -50,7 +50,7 @@ public Pattern findLastWord() {
* @return a pattern that looks for numbers
*/
public Pattern findAllNumbers() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\d+");
}
/**
@@ -59,7 +59,7 @@ public Pattern findAllNumbers() {
* @return a pattern that looks for dates
*/
public Pattern findDates() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
}
/**
@@ -69,7 +69,7 @@ public Pattern findDates() {
* @return a pattern that looks for different variations of word "color"
*/
public Pattern findDifferentSpellingsOfColor() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("colou?rs?");
}
/**
@@ -80,7 +80,7 @@ public Pattern findDifferentSpellingsOfColor() {
* @return a pattern that looks for zip codes
*/
public Pattern findZipCodes() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\s\\d{5}\\s");
}
/**
@@ -90,7 +90,7 @@ public Pattern findZipCodes() {
* @return a pattern that looks for different variations of word "link"
*/
public Pattern findDifferentSpellingsOfLink() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("l[yi (]nk");
}
/**
@@ -100,7 +100,7 @@ public Pattern findDifferentSpellingsOfLink() {
* @return a pattern that looks for phone numbers
*/
public Pattern findSimplePhoneNumber() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d");
}
/**
@@ -111,7 +111,7 @@ public Pattern findSimplePhoneNumber() {
* @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();
+ return Pattern.compile("[0-5]{3}");
}
/**
@@ -120,7 +120,7 @@ public Pattern findNumbersFromZeroToFiveWithLengthThree() {
* @return a pattern that looks for the words that have length 5
*/
public Pattern findAllWordsWithFiveLength() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\b[A-Za-z]{5}\\b");
}
/**
@@ -131,7 +131,7 @@ public Pattern findAllWordsWithFiveLength() {
* @return a pattern that looks for words and numbers that not shorter 2 and not longer 3
*/
public Pattern findAllLettersAndDigitsWithLengthThree() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\b\\w{2,3}\\b");
}
/**
@@ -140,7 +140,7 @@ public Pattern findAllLettersAndDigitsWithLengthThree() {
* @return a pattern that looks for the words that begin with capital letter
*/
public Pattern findAllWordsWhichBeginWithCapitalLetter() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\b[A-Z][a-z]*\\b");
}
/**
@@ -150,7 +150,7 @@ public Pattern findAllWordsWhichBeginWithCapitalLetter() {
* @return a pattern that looks for the abbreviations above
*/
public Pattern findAbbreviation() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("A[KLRZ]|C[AOT]|P[RAD]");
}
/**
@@ -159,7 +159,7 @@ public Pattern findAbbreviation() {
* @return a pattern that looks for all open braces
*/
public Pattern findAllOpenBraces() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("(\\{+)");
}
/**
@@ -168,7 +168,7 @@ public Pattern findAllOpenBraces() {
* @return a pattern that looks for everything inside []
*/
public Pattern findOnlyResources() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("(?<=\\[).+?(?=\\])");
}
/**
@@ -177,7 +177,7 @@ public Pattern findOnlyResources() {
* @return a pattern that looks for all https links in note.txt
*/
public Pattern findOnlyLinksInNote() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("https://((www.)?+[\\w]+(.))com");
}
/**
@@ -186,7 +186,7 @@ public Pattern findOnlyLinksInNote() {
* @return a pattern that looks for all http links in nasa.json
*/
public Pattern findOnlyLinksInJson() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("http://(.*)JPG");
}
/**
@@ -195,7 +195,7 @@ public Pattern findOnlyLinksInJson() {
* @return a pattern that looks for all .com, .net and .edu emails
*/
public Pattern findAllEmails() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("[\\w.]+@[\\w]+\\.(net|com|edu)");
}
/**
@@ -207,7 +207,7 @@ public Pattern findAllEmails() {
* @return a pattern that looks for phone numbers patterns above
*/
public Pattern findAllPatternsForPhoneNumbers() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\(?\\d{3}[-.)]\\d{3}[-.]\\d{4}");
}
/**
@@ -216,7 +216,7 @@ public Pattern findAllPatternsForPhoneNumbers() {
* @return a pattern that looks for duplicates
*/
public Pattern findOnlyDuplicates() {
- throw new ExerciseNotCompletedException();
+ return Pattern.compile("\\b(\\w+)\\s\\1\\b");
}
/**
@@ -227,7 +227,8 @@ public Pattern findOnlyDuplicates() {
* @return String where all names recorded as last name first name
*/
public String replaceFirstAndLastNames(String names) {
- throw new ExerciseNotCompletedException();
+ var matcher = Pattern.compile("(\\w+),\\s+(\\w+)").matcher(names);
+ return matcher.replaceAll("$2 $1");
}
/**
@@ -238,7 +239,8 @@ public String replaceFirstAndLastNames(String names) {
* @return String where in all phone numbers last 7 digits replaced to X
*/
public String replaceLastSevenDigitsOfPhoneNumberToX(String phones) {
- throw new ExerciseNotCompletedException();
+ var matcher = Pattern.compile("\\(?(\\d{3})[-.)]\\d{3}[-.]\\d{4}").matcher(phones);
+ return matcher.replaceAll("$1-XXX-XXXX");
}
/**
@@ -250,6 +252,7 @@ public String replaceLastSevenDigitsOfPhoneNumberToX(String phones) {
* @return String where all resources embraced in href
*/
public String insertLinksAndResourcesIntoHref(String links) {
- throw new ExerciseNotCompletedException();
+ var matcher = Pattern.compile("\\[(.*?)]\\((http.*?)\\)").matcher(links);
+ return matcher.replaceAll("$1 ");
}
}
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..0e68b210f 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,8 +1,14 @@
package com.bobocode.se;
import com.bobocode.util.ExerciseNotCompletedException;
+import lombok.SneakyThrows;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
import java.util.Comparator;
+import static java.util.Objects.requireNonNull;
+
/**
* A generic comparator that is comparing a random field of the given class. The field is either primitive or
* {@link Comparable}. It is chosen during comparator instance creation and is used for all comparisons.
@@ -18,8 +24,19 @@
*/
public class RandomFieldComparator implements Comparator {
+ private final Class targetType;
+
+ private final Field fieldToCompare;
+
public RandomFieldComparator(Class targetType) {
- throw new ExerciseNotCompletedException(); // todo: implement this constructor;
+ this.targetType = requireNonNull(targetType);
+ this.fieldToCompare = chooseFieldToCompare(targetType);
+ }
+
+ private Field chooseFieldToCompare(Class targetType) {
+ return Arrays.stream(targetType.getDeclaredFields())
+ .filter(f -> Comparable.class.isAssignableFrom(f.getType()) || f.getType().isPrimitive())
+ .findAny().orElseThrow(() -> new IllegalArgumentException("There are no fields available to compare"));
}
/**
@@ -34,14 +51,26 @@ public RandomFieldComparator(Class targetType) {
*/
@Override
public int compare(T o1, T o2) {
- throw new ExerciseNotCompletedException(); // todo: implement this method;
+ requireNonNull(o1);
+ requireNonNull(o2);
+ return compareFieldValues(o1, o2);
+ }
+
+ @SneakyThrows
+ @SuppressWarnings("unchecked")
+ private > int compareFieldValues(T o1, T o2) {
+ fieldToCompare.setAccessible(true);
+ var value1 = (U) fieldToCompare.get(o1);
+ var value2 = (U) fieldToCompare.get(o2);
+ Comparator comparator = Comparator.nullsLast(Comparator.naturalOrder());
+ return comparator.compare(value1, value2);
}
/**
* Returns the name of the randomly-chosen comparing field.
*/
public String getComparingFieldName() {
- throw new ExerciseNotCompletedException(); // todo: implement this method;
+ return fieldToCompare.getName();
}
/**
@@ -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'", targetType.getSimpleName(),
+ getComparingFieldName());
}
}
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
index 3e58c3b33..f4696c9ec 100644
--- 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
@@ -1,7 +1,6 @@
package com.bobocode.oop.data;
-import com.bobocode.util.ExerciseNotCompletedException;
-
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -12,8 +11,9 @@
* 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<>();
+public class FlightDao implements IFlightDao {
+
+ private final Set flights = new HashSet<>();
/**
* Stores a new flight number
@@ -21,8 +21,12 @@ public class FlightDao {
* @param flightNumber a flight number to store
* @return {@code true} if a flight number was stored, {@code false} otherwise
*/
+ @Override
public boolean register(String flightNumber) {
- throw new ExerciseNotCompletedException();// todo: implement this method
+ if (!flights.contains(flightNumber)) {
+ this.flights.add(flightNumber);
+ return true;
+ } else return false;
}
/**
@@ -30,8 +34,9 @@ public boolean register(String flightNumber) {
*
* @return a set of flight numbers
*/
+ @Override
public Set findAll() {
- throw new ExerciseNotCompletedException();// todo: implement this method
+ return Collections.unmodifiableSet(flights);
}
}
diff --git a/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/IFlightDao.java b/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/IFlightDao.java
new file mode 100644
index 000000000..6691d2d3e
--- /dev/null
+++ b/4-0-object-oriented-programming/4-3-1-flight-search/src/main/java/com/bobocode/oop/data/IFlightDao.java
@@ -0,0 +1,10 @@
+package com.bobocode.oop.data;
+
+import java.util.Set;
+
+public interface IFlightDao {
+
+ boolean register(String flightNumber);
+
+ Set findAll();
+}
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
index 8cd2ed673..92b7d9331 100644
--- 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
@@ -16,6 +16,6 @@ public class FlightServiceFactory {
* @return FlightService
*/
public FlightService creteFlightService() {
- throw new ExerciseNotCompletedException();
+ return new FlightService();
}
}
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
index b31cd8f07..1cd9f5d49 100644
--- 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
@@ -1,8 +1,11 @@
package com.bobocode.oop.service;
+import com.bobocode.oop.data.FlightDao;
+import com.bobocode.oop.data.IFlightDao;
import com.bobocode.util.ExerciseNotCompletedException;
import java.util.List;
+import java.util.Set;
/**
* {@link FlightService} provides an API that allows to manage flight numbers
@@ -12,6 +15,16 @@
*/
public class FlightService {
+ private final IFlightDao flightDao;
+
+ public FlightService() {
+ this.flightDao = new FlightDao();
+ }
+
+ public FlightService(IFlightDao flightDao) {
+ this.flightDao = flightDao;
+ }
+
/**
* Adds a new flight number
*
@@ -19,7 +32,7 @@ public class FlightService {
* @return {@code true} if a flight number was added, {@code false} otherwise
*/
public boolean registerFlight(String flightNumber) {
- throw new ExerciseNotCompletedException();
+ return flightDao.register(flightNumber);
}
/**
@@ -29,6 +42,6 @@ public boolean registerFlight(String flightNumber) {
* @return a list of found flight numbers
*/
public List searchFlights(String query) {
- throw new ExerciseNotCompletedException();
+ return flightDao.findAll().stream().filter(flightId -> flightId.contains(query)).toList();
}
}
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..87f667875 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
@@ -28,6 +28,11 @@ private Functions() {
public static FunctionMap intFunctionMap() {
FunctionMap intFunctionMap = new FunctionMap<>();
+ intFunctionMap.addFunction("abs", x -> Math.abs(x));
+ intFunctionMap.addFunction("sgn", x -> Integer.signum(x));
+ intFunctionMap.addFunction("increment", x -> x + 1);
+ intFunctionMap.addFunction("decrement", x -> x - 1);
+ intFunctionMap.addFunction("square", x -> x * x);
// todo: according to the javadoc add functions using lambda expression
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..9969471c3 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..d0d233af4 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,8 @@
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.function.*;
/**
@@ -27,7 +29,7 @@ public class CrazyLambdas {
* @return a string supplier
*/
public static Supplier helloSupplier() {
- throw new ExerciseNotCompletedException();
+ return () -> "Hello";
}
/**
@@ -36,7 +38,7 @@ public static Supplier helloSupplier() {
* @return a string predicate
*/
public static Predicate isEmptyPredicate() {
- throw new ExerciseNotCompletedException();
+ return (x) -> x == null || x.isEmpty();
}
/**
@@ -46,7 +48,15 @@ public static Predicate isEmptyPredicate() {
* @return function that repeats Strings
*/
public static BiFunction stringMultiplier() {
- throw new ExerciseNotCompletedException();
+ return (x, n) -> {
+ if (n > 0) {
+ String res = x;
+ for (int i = 1; i < n; i++) {
+ res += x;
+ }
+ return res;
+ } else return x;
+ };
}
/**
@@ -56,7 +66,7 @@ public static BiFunction stringMultiplier() {
* @return function that converts adds dollar sign
*/
public static Function toDollarStringFunction() {
- throw new ExerciseNotCompletedException();
+ return (decimal) -> "$" + decimal.toPlainString();
}
/**
@@ -68,7 +78,7 @@ public static Function toDollarStringFunction() {
* @return a string predicate
*/
public static Predicate lengthInRangePredicate(int min, int max) {
- throw new ExerciseNotCompletedException();
+ return (x) -> x.length() >= min && x.length() <= max;
}
/**
@@ -77,7 +87,7 @@ public static Predicate lengthInRangePredicate(int min, int max) {
* @return int supplier
*/
public static IntSupplier randomIntSupplier() {
- throw new ExerciseNotCompletedException();
+ return () -> ThreadLocalRandom.current().nextInt();
}
@@ -87,7 +97,7 @@ public static IntSupplier randomIntSupplier() {
* @return int operation
*/
public static IntUnaryOperator boundedRandomIntSupplier() {
- throw new ExerciseNotCompletedException();
+ return (i) -> ThreadLocalRandom.current().nextInt(i);
}
/**
@@ -96,7 +106,7 @@ public static IntUnaryOperator boundedRandomIntSupplier() {
* @return square operation
*/
public static IntUnaryOperator intSquareOperation() {
- throw new ExerciseNotCompletedException();
+ return (i) -> i * i;
}
/**
@@ -105,7 +115,7 @@ public static IntUnaryOperator intSquareOperation() {
* @return binary sum operation
*/
public static LongBinaryOperator longSumOperation() {
- throw new ExerciseNotCompletedException();
+ return Long::sum;
}
/**
@@ -114,7 +124,7 @@ public static LongBinaryOperator longSumOperation() {
* @return string to int converter
*/
public static ToIntFunction stringToIntConverter() {
- throw new ExerciseNotCompletedException();
+ return Integer::parseInt;
}
/**
@@ -125,7 +135,7 @@ public static ToIntFunction stringToIntConverter() {
* @return a function supplier
*/
public static Supplier nMultiplyFunctionSupplier(int n) {
- throw new ExerciseNotCompletedException();
+ return () -> (x) -> x * n;
}
/**
@@ -134,7 +144,7 @@ public static Supplier nMultiplyFunctionSupplier(int n) {
* @return function that composes functions with trim() function
*/
public static UnaryOperator> composeWithTrimFunction() {
- throw new ExerciseNotCompletedException();
+ return (func) -> func.compose(String::trim);
}
/**
@@ -145,7 +155,11 @@ public static UnaryOperator> composeWithTrimFunction()
* @return a thread supplier
*/
public static Supplier runningThreadSupplier(Runnable runnable) {
- throw new ExerciseNotCompletedException();
+ return () -> {
+ var res = new Thread(runnable);
+ res.start();
+ return res;
+ };
}
/**
@@ -154,7 +168,7 @@ public static Supplier runningThreadSupplier(Runnable runnable) {
* @return a runnable consumer
*/
public static Consumer newThreadRunnableConsumer() {
- throw new ExerciseNotCompletedException();
+ return (r) -> new Thread(r).start();
}
/**
@@ -164,7 +178,11 @@ public static Consumer newThreadRunnableConsumer() {
* @return a function that transforms runnable into a thread supplier
*/
public static Function> runnableToThreadSupplierFunction() {
- throw new ExerciseNotCompletedException();
+ return (r) -> (Supplier) () -> {
+ var res = new Thread(r);
+ res.start();
+ return res;
+ };
}
/**
@@ -177,7 +195,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 (intOperation, intPredicate) -> a -> intPredicate.test(a) ? intOperation.applyAsInt(a) : a;
}
/**
@@ -188,7 +206,12 @@ 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 (stringIntUnaryOperatorMap, s) -> {
+ if (stringIntUnaryOperatorMap.containsKey(s)) {
+ return stringIntUnaryOperatorMap.get(s);
+ }
+ return IntUnaryOperator.identity();
+ };
}
/**
@@ -206,7 +229,7 @@ public static BiFunction, String, IntUnaryOperator
* @return a comparator instance
*/
public static > Comparator comparing(Function super T, ? extends U> mapper) {
- throw new ExerciseNotCompletedException();
+ return Comparator.comparing((T o) -> mapper.apply(o));
}
/**
@@ -226,7 +249,14 @@ public static > Comparator comparing(Funct
*/
public static > Comparator thenComparing(
Comparator super T> comparator, Function super T, ? extends U> mapper) {
- throw new ExerciseNotCompletedException();
+ return (o1, o2) -> {
+ int result = comparator.compare(o1, o2);
+ if (result == 0) {
+ return comparing(mapper).compare(o1, o2);
+ } else {
+ return result;
+ }
+ };
}
/**
@@ -235,7 +265,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..2518c1917 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,19 @@
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 java.math.BigDecimal;
import java.time.Month;
import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.*;
/**
* {@link CrazyStreams} is an exercise class. Each method represent some operation with a collection of accounts that
@@ -22,6 +29,7 @@
*/
@AllArgsConstructor
public class CrazyStreams {
+
private Collection accounts;
/**
@@ -30,7 +38,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 +48,7 @@ public Optional findRichestPerson() {
* @return a list of accounts
*/
public List findAccountsByBirthdayMonth(Month birthdayMonth) {
- throw new ExerciseNotCompletedException();
+ return accounts.stream().filter(acc -> birthdayMonth.equals(acc.getBirthday().getMonth())).toList();
}
/**
@@ -50,7 +58,7 @@ 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(groupingBy(a -> Sex.MALE == a.getSex()));
}
/**
@@ -60,7 +68,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(groupingBy(a -> a.getEmail().split("@")[1]));
}
/**
@@ -69,7 +77,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(a -> a.getFirstName().length() + a.getLastName().length())
+ .sum();
}
/**
@@ -78,7 +88,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 +97,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)).toList();
}
/**
@@ -97,7 +107,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(acc -> acc.getEmail().endsWith(emailDomain));
}
/**
@@ -108,7 +118,8 @@ public boolean containsAccountWithEmailDomain(String emailDomain) {
* @return account balance
*/
public BigDecimal getBalanceByEmail(String email) {
- throw new ExerciseNotCompletedException();
+ return accounts.stream().filter(acc -> acc.getEmail().equals(email)).findFirst()
+ .orElseThrow(() -> new EntityNotFoundException("Cannot find Account by email=" + email)).getBalance();
}
/**
@@ -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, Function.identity()));
}
/**
@@ -128,7 +139,7 @@ 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 +149,8 @@ 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(groupingBy(Account::getLastName, TreeMap::new,
+ mapping(Account::getFirstName, toSet())));
}
/**
@@ -148,7 +160,9 @@ 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(groupingBy(a -> a.getBirthday().getMonth(),
+ mapping(Account::getFirstName, joining(", "))));
}
/**
@@ -158,7 +172,10 @@ 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(groupingBy(a -> a.getCreationDate().getMonth(),
+ mapping(Account::getBalance,
+ reducing(BigDecimal.ZERO, BigDecimal::add))));
}
/**
@@ -168,7 +185,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(groupingBy(Function.identity(), counting()));
}
/**
@@ -179,7 +200,13 @@ 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(a -> Stream.of(a.getFirstName(), a.getLastName()))
+ .filter(s -> s.length() >= nameLengthBound)
+ .map(String::toLowerCase)
+ .flatMapToInt(String::chars)
+ .mapToObj(c -> (char) c)
+ .collect(groupingBy(Function.identity(), 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..67dc7a8c1 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
@@ -16,6 +16,8 @@
import java.util.Optional;
import java.util.OptionalDouble;
+import static java.util.Comparator.comparing;
+
/**
* {@link CrazyOptionals} is an exercise class. Each method represents some operation with a {@link Account} and
* should be implemented using Optional API. Every method that is not implemented yet throws
@@ -37,7 +39,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 +49,7 @@ 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 +59,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 +71,7 @@ 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 +82,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 +93,7 @@ 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 +103,7 @@ public static Account getOrGenerateAccount(AccountProvider accountProvider) {
* @return optional balance
*/
public static Optional