diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md new file mode 100644 index 0000000000..574f61ac6a --- /dev/null +++ b/core-java-modules/core-java-collections/README.md @@ -0,0 +1,16 @@ +## Core Java Collections + +This module contains articles about Java collections + +### Relevant Articles: +- [Introduction to the Java ArrayDeque](https://www.baeldung.com/java-array-deque) +- [An Introduction to Java.util.Hashtable Class](https://www.baeldung.com/java-hash-table) +- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe) +- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity) +- [A Guide to EnumMap](https://www.baeldung.com/java-enum-map) +- [A Guide to Iterator in Java](https://www.baeldung.com/java-iterator) +- [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack) +- [Guide to the Java Queue Interface](https://www.baeldung.com/java-queue) +- [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) +- [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list) +- More articles: [[next -->]](/core-java-modules/core-java-collections-2) diff --git a/core-java-modules/core-java-collections/pom.xml b/core-java-modules/core-java-collections/pom.xml new file mode 100644 index 0000000000..3c5c70af82 --- /dev/null +++ b/core-java-modules/core-java-collections/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + core-java-collections + 0.1.0-SNAPSHOT + core-java-collections + jar + + + com.ossez.core-java-modules + core-java-modules + 0.0.2-SNAPSHOT + + + + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStack.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStack.java new file mode 100644 index 0000000000..24b2a6d387 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStack.java @@ -0,0 +1,37 @@ +package com.ossez.charstack; + +import java.util.Iterator; +import java.util.LinkedList; + +public class CharStack { + + private LinkedList items; + + public CharStack() { + this.items = new LinkedList(); + } + + public void push(Character item) { + items.push(item); + } + + public Character peek() { + return items.getFirst(); + } + + public Character pop() { + + Iterator iter = items.iterator(); + Character item = iter.next(); + if (item != null) { + iter.remove(); + return item; + } + return null; + } + + public int size() { + return items.size(); + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStackWithArray.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStackWithArray.java new file mode 100644 index 0000000000..2780db0cb2 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/CharStackWithArray.java @@ -0,0 +1,48 @@ +package com.ossez.charstack; + +public class CharStackWithArray { + + private char[] elements; + private int size; + + public CharStackWithArray() { + size = 0; + elements = new char[4]; + } + + public int size() { + return size; + } + + public char peek() { + if (size == 0) { + throw new EmptyStackException(); + } + return elements[size - 1]; + } + + public char pop() { + if (size == 0) { + throw new EmptyStackException(); + } + + return elements[--size]; + } + + public void push(char item) { + ensureCapacity(size + 1); + elements[size] = item; + size++; + } + + private void ensureCapacity(int newSize) { + char newBiggerArray[]; + + if (elements.length < newSize) { + newBiggerArray = new char[elements.length * 2]; + System.arraycopy(elements, 0, newBiggerArray, 0, size); + elements = newBiggerArray; + } + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/EmptyStackException.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/EmptyStackException.java new file mode 100644 index 0000000000..968a3ee213 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/charstack/EmptyStackException.java @@ -0,0 +1,9 @@ +package com.ossez.charstack; + +public class EmptyStackException extends RuntimeException { + + public EmptyStackException() { + super("Stack is empty"); + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java new file mode 100644 index 0000000000..bb0fc4bf22 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToList.java @@ -0,0 +1,49 @@ +package com.ossez.collections.convertarrayprimitives; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.apache.commons.lang3.ArrayUtils; + +import com.google.common.primitives.Ints; + +public class ConvertPrimitivesArrayToList { + + public static void failConvert() { + int[] input = new int[]{1,2,3,4}; + // List inputAsList = Arrays.asList(input); + } + + public static List iterateConvert(int[] input) { + List output = new ArrayList(); + for (int value : input) { + output.add(value); + } + return output; + } + + public static List streamConvert(int[] input) { + List output = Arrays.stream(input).boxed().collect(Collectors.toList()); + return output; + } + + public static List streamConvertIntStream(int[] input) { + List output = IntStream.of(input).boxed().collect(Collectors.toList()); + return output; + } + + public static List guavaConvert(int[] input) { + List output = Ints.asList(input); + return output; + } + + public static List apacheCommonConvert(int[] input) { + Integer[] outputBoxed = ArrayUtils.toObject(input); + List output = Arrays.asList(outputBoxed); + return output; + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/hashtable/Word.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/hashtable/Word.java new file mode 100644 index 0000000000..ddeeea24d8 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/hashtable/Word.java @@ -0,0 +1,28 @@ +package com.ossez.hashtable; + +public class Word { + private String name; + + public Word(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof Word)) + return false; + + Word word = (Word) o; + return word.getName().equals(this.name) ? true : false; + + } + + public int hashCode() { + return name.hashCode(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/iteratorguide/IteratorGuide.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/iteratorguide/IteratorGuide.java new file mode 100644 index 0000000000..91d4b27024 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/iteratorguide/IteratorGuide.java @@ -0,0 +1,39 @@ +package com.ossez.iteratorguide; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +public class IteratorGuide { + + public static void main(String[] args) { + List items = new ArrayList<>(); + items.add("ONE"); + items.add("TWO"); + items.add("THREE"); + Iterator iter = items.iterator(); + while (iter.hasNext()) { + String next = iter.next(); + System.out.println(next); + iter.remove(); + } + ListIterator listIterator = items.listIterator(); + while(listIterator.hasNext()) { + String nextWithIndex = items.get(listIterator.nextIndex()); + String next = listIterator.next(); + if( "ONE".equals(next)) { + listIterator.set("SWAPPED"); + } + } + listIterator.add("FOUR"); + while(listIterator.hasPrevious()) { + String previousWithIndex = items.get(listIterator.previousIndex()); + String previous = listIterator.previous(); + System.out.println(previous); + } + listIterator.forEachRemaining(e -> { + System.out.println(e); + }); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/CopyOnWriteBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/CopyOnWriteBenchmark.java new file mode 100644 index 0000000000..4479263d0c --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/CopyOnWriteBenchmark.java @@ -0,0 +1,78 @@ +package com.ossez.performance; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 10) +public class CopyOnWriteBenchmark { + + @State(Scope.Thread) + public static class MyState { + + CopyOnWriteArrayList employeeList = new CopyOnWriteArrayList<>(); + + long iterations = 100000; + + Employee employee = new Employee(100L, "Harry"); + + int employeeIndex = -1; + + @Setup(Level.Trial) + public void setUp() { + for (long i = 0; i < iterations; i++) { + employeeList.add(new Employee(i, "John")); + } + + employeeList.add(employee); + + employeeIndex = employeeList.indexOf(employee); + } + } + + @Benchmark + public void testAdd(CopyOnWriteBenchmark.MyState state) { + state.employeeList.add(new Employee(state.iterations + 1, "John")); + } + + @Benchmark + public void testAddAt(CopyOnWriteBenchmark.MyState state) { + state.employeeList.add((int) (state.iterations), new Employee(state.iterations, "John")); + } + + @Benchmark + public boolean testContains(CopyOnWriteBenchmark.MyState state) { + return state.employeeList.contains(state.employee); + } + + @Benchmark + public int testIndexOf(CopyOnWriteBenchmark.MyState state) { + return state.employeeList.indexOf(state.employee); + } + + @Benchmark + public Employee testGet(CopyOnWriteBenchmark.MyState state) { + return state.employeeList.get(state.employeeIndex); + } + + @Benchmark + public boolean testRemove(CopyOnWriteBenchmark.MyState state) { + return state.employeeList.remove(state.employee); + } + + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(CopyOnWriteBenchmark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/Employee.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/Employee.java new file mode 100644 index 0000000000..286ab79c09 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/Employee.java @@ -0,0 +1,55 @@ +package com.ossez.performance; + +public class Employee { + + private Long id; + private String name; + + public Employee(Long id, String name) { + this.name = name; + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Employee employee = (Employee) o; + + if (!id.equals(employee.id)) return false; + return name.equals(employee.name); + + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + + @Override + public String toString() { + return "Employee{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/HashMapBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/HashMapBenchmark.java new file mode 100644 index 0000000000..f4c4a65491 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/HashMapBenchmark.java @@ -0,0 +1,73 @@ +package com.ossez.performance; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 10) +public class HashMapBenchmark { + + @State(Scope.Thread) + public static class MyState { + + Map employeeMap = new HashMap<>(); + //LinkedHashMap employeeMap = new LinkedHashMap<>(); + //IdentityHashMap employeeMap = new IdentityHashMap<>(); + //WeakHashMap employeeMap = new WeakHashMap<>(); + //ConcurrentHashMap employeeMap = new ConcurrentHashMap<>(); + //ConcurrentSkipListMap employeeMap = new ConcurrentSkipListMap <>(); + + // TreeMap + + long iterations = 100000; + + Employee employee = new Employee(100L, "Harry"); + + int employeeIndex = -1; + + @Setup(Level.Trial) + public void setUp() { + for (long i = 0; i < iterations; i++) { + employeeMap.put(i, new Employee(i, "John")); + } + + //employeeMap.put(iterations, employee); + } + } + + @Benchmark + public Employee testGet(HashMapBenchmark.MyState state) { + return state.employeeMap.get(state.iterations); + } + + @Benchmark + public Employee testRemove(HashMapBenchmark.MyState state) { + return state.employeeMap.remove(state.iterations); + } + + @Benchmark + public Employee testPut(HashMapBenchmark.MyState state) { + return state.employeeMap.put(state.employee.getId(), state.employee); + } + + @Benchmark + public Boolean testContainsKey(HashMapBenchmark.MyState state) { + return state.employeeMap.containsKey(state.employee.getId()); + } + + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(HashMapBenchmark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/SetBenchMark.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/SetBenchMark.java new file mode 100644 index 0000000000..23957e4b67 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/performance/SetBenchMark.java @@ -0,0 +1,62 @@ +package com.ossez.performance; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.LinkedHashSet; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 10) +public class SetBenchMark { + + @State(Scope.Thread) + public static class MyState { + + //Set employeeSet = new HashSet<>(); + LinkedHashSet employeeSet = new LinkedHashSet<>(); + //ConcurrentSkipListSet employeeSet = new ConcurrentSkipListSet <>(); + + // TreeSet  + + long iterations = 1000; + Employee employee = new Employee(100L, "Harry"); + + @Setup(Level.Trial) + public void setUp() { + for (long i = 0; i < iterations; i++) { + employeeSet.add(new Employee(i, "John")); + } + + //employeeSet.add(employee); + } + } + + @Benchmark + public boolean testAdd(SetBenchMark.MyState state) { + return state.employeeSet.add(state.employee); + } + + @Benchmark + public Boolean testContains(SetBenchMark.MyState state) { + return state.employeeSet.contains(state.employee); + } + + @Benchmark + public boolean testRemove(SetBenchMark.MyState state) { + return state.employeeSet.remove(state.employee); + } + + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(SetBenchMark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/queueInterface/CustomBaeldungQueue.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/queueInterface/CustomBaeldungQueue.java new file mode 100644 index 0000000000..65c2c09cde --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/queueInterface/CustomBaeldungQueue.java @@ -0,0 +1,48 @@ +package com.ossez.queueInterface; + +import java.util.AbstractQueue; +import java.util.Iterator; +import java.util.LinkedList; + +public class CustomBaeldungQueue extends AbstractQueue { + + private LinkedList elements; + + public CustomBaeldungQueue() { + this.elements = new LinkedList(); + } + + @Override + public Iterator iterator() { + return elements.iterator(); + } + + @Override + public int size() { + return elements.size(); + } + + @Override + public boolean offer(T t) { + if(t == null) return false; + elements.add(t); + return true; + } + + @Override + public T poll() { + + Iterator iter = elements.iterator(); + T t = iter.next(); + if(t != null){ + iter.remove(); + return t; + } + return null; + } + + @Override + public T peek() { + return elements.getFirst(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/synchronizedcollections/Application.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/synchronizedcollections/Application.java new file mode 100644 index 0000000000..d1acf3daaa --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/synchronizedcollections/Application.java @@ -0,0 +1,18 @@ +package com.ossez.synchronizedcollections; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +public class Application { + + private static final Logger LOGGER = Logger.getLogger(Application.class.getName()); + + public static void main(String[] args) throws InterruptedException { + List syncCollection = Collections.synchronizedList(Arrays.asList(1, 2, 3, 4, 5, 6)); + synchronized (syncCollection) { + syncCollection.forEach((e) -> {LOGGER.info(e.toString());}); + } + } +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/ossez/thread_safe_lifo/DequeBasedSynchronizedStack.java b/core-java-modules/core-java-collections/src/main/java/com/ossez/thread_safe_lifo/DequeBasedSynchronizedStack.java new file mode 100644 index 0000000000..4f835d6fc8 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/ossez/thread_safe_lifo/DequeBasedSynchronizedStack.java @@ -0,0 +1,36 @@ +package com.ossez.thread_safe_lifo; + +import java.util.ArrayDeque; + +/** + * Deque Based Stack implementation. + */ +public class DequeBasedSynchronizedStack { + + // Internal Deque which gets decorated for synchronization. + private ArrayDeque dequeStore = new ArrayDeque<>(); + + public DequeBasedSynchronizedStack(int initialCapacity) { + this.dequeStore = new ArrayDeque<>(initialCapacity); + } + + public DequeBasedSynchronizedStack() { + + } + + public synchronized T pop() { + return this.dequeStore.pop(); + } + + public synchronized void push(T element) { + this.dequeStore.push(element); + } + + public synchronized T peek() { + return this.dequeStore.peek(); + } + + public synchronized int size() { + return this.dequeStore.size(); + } +} diff --git a/core-java-modules/core-java-collections/src/main/resources/logback.xml b/core-java-modules/core-java-collections/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/arraydeque/ArrayDequeUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/arraydeque/ArrayDequeUnitTest.java new file mode 100644 index 0000000000..a2be5eb520 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/arraydeque/ArrayDequeUnitTest.java @@ -0,0 +1,50 @@ +package com.ossez.arraydeque; + +import java.util.ArrayDeque; +import java.util.Deque; + +import static org.junit.Assert.*; +import org.junit.Test; + +public class ArrayDequeUnitTest { + + @Test + public void whenOffer_addsAtLast() { + final Deque deque = new ArrayDeque<>(); + + deque.offer("first"); + deque.offer("second"); + + assertEquals("second", deque.getLast()); + } + + @Test + public void whenPoll_removesFirst() { + final Deque deque = new ArrayDeque<>(); + + deque.offer("first"); + deque.offer("second"); + + assertEquals("first", deque.poll()); + } + + @Test + public void whenPush_addsAtFirst() { + final Deque deque = new ArrayDeque<>(); + + deque.push("first"); + deque.push("second"); + + assertEquals("second", deque.getFirst()); + } + + @Test + public void whenPop_removesLast() { + final Deque deque = new ArrayDeque<>(); + + deque.push("first"); + deque.push("second"); + + assertEquals("second", deque.pop()); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUnitTest.java new file mode 100644 index 0000000000..1b306cb5d3 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUnitTest.java @@ -0,0 +1,50 @@ +package com.ossez.charstack; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CharStackUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + CharStack charStack = new CharStack(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + CharStack charStack = new CharStack(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + CharStack charStack = new CharStack(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + CharStack charStack = new CharStack(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUsingJavaUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUsingJavaUnitTest.java new file mode 100644 index 0000000000..f114dd6ea5 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackUsingJavaUnitTest.java @@ -0,0 +1,53 @@ +package com.ossez.charstack; + +import static org.junit.Assert.assertEquals; + +import java.util.Stack; + +import org.junit.jupiter.api.Test; + +public class CharStackUsingJavaUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + Stack charStack = new Stack<>(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + Stack charStack = new Stack<>(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + Stack charStack = new Stack<>(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + + Stack charStack = new Stack<>(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackWithArrayUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackWithArrayUnitTest.java new file mode 100644 index 0000000000..d0fdf43f57 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/charstack/CharStackWithArrayUnitTest.java @@ -0,0 +1,65 @@ +package com.ossez.charstack; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CharStackWithArrayUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + CharStackWithArray charStack = new CharStackWithArray(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + CharStackWithArray charStack = new CharStackWithArray(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenEmptyCharStack_when5ElementIsPushed_thenStackSizeis() { + + CharStackWithArray charStack = new CharStackWithArray(); + + charStack.push('A'); + charStack.push('B'); + charStack.push('C'); + charStack.push('D'); + charStack.push('E'); + + assertEquals(5, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + CharStackWithArray charStack = new CharStackWithArray(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + + CharStackWithArray charStack = new CharStackWithArray(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java new file mode 100644 index 0000000000..ec4474fa61 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/collections/convertarrayprimitives/ConvertPrimitivesArrayToListUnitTest.java @@ -0,0 +1,35 @@ +package com.ossez.collections.convertarrayprimitives; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; + +public class ConvertPrimitivesArrayToListUnitTest { + + @Test + public void givenArrayWithPrimitives_whenIterativeConvert_thenArrayGetsConverted() { + assertEquals(Arrays.asList(1,2,3,4), ConvertPrimitivesArrayToList.iterateConvert(new int[]{1,2,3,4})); + } + + @Test + public void givenArrayWithPrimitives_whenStreamConvert_thenArrayGetsConverted() { + assertEquals(Arrays.asList(1,2,3,4), ConvertPrimitivesArrayToList.streamConvert(new int[]{1,2,3,4})); + } + + @Test + public void givenArrayWithPrimitives_whenIntStreamConvert_thenArrayGetsConverted() { + assertEquals(Arrays.asList(1,2,3,4), ConvertPrimitivesArrayToList.streamConvertIntStream(new int[]{1,2,3,4})); + } + + @Test + public void givenArrayWithPrimitives_whenGuavaConvert_thenArrayGetsConverted() { + assertEquals(Arrays.asList(1,2,3,4), ConvertPrimitivesArrayToList.guavaConvert(new int[]{1,2,3,4})); + } + + @Test + public void givenArrayWithPrimitives_whenApacheCommonConvert_thenArrayGetsConverted() { + assertEquals(Arrays.asList(1,2,3,4), ConvertPrimitivesArrayToList.apacheCommonConvert(new int[]{1,2,3,4})); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/DummyEnum.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/DummyEnum.java new file mode 100644 index 0000000000..614e818352 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/DummyEnum.java @@ -0,0 +1,13 @@ +package com.ossez.enummap; + +/** + * This enum is used for benchmarking, therefore has many values. + */ +public enum DummyEnum { + CCC_000, + CCC_001,CCC_002,CCC_003,CCC_004,CCC_005,CCC_006,CCC_007,CCC_008,CCC_009,CCC_010, + CCC_011,CCC_012,CCC_013,CCC_014,CCC_015,CCC_016,CCC_017,CCC_018,CCC_019,CCC_020, + CCC_021,CCC_022,CCC_023,CCC_024,CCC_025,CCC_026,CCC_027,CCC_028,CCC_029,CCC_030, + CCC_031,CCC_032,CCC_033,CCC_034,CCC_035,CCC_036,CCC_037,CCC_038,CCC_039,CCC_040, + CCC_041,CCC_042,CCC_043,CCC_044,CCC_045,CCC_046,CCC_047,CCC_048,CCC_049, +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapBenchmarkLiveTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapBenchmarkLiveTest.java new file mode 100644 index 0000000000..5de9563b39 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapBenchmarkLiveTest.java @@ -0,0 +1,119 @@ +package com.ossez.enummap; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode({ Mode.AverageTime }) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +public class EnumMapBenchmarkLiveTest { + + @State(Scope.Thread) + public static class BenchmarkState { + EnumMap enumMap = new EnumMap<>(DummyEnum.class); + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + int len = DummyEnum.values().length; + Random random = new Random(); + int randomIndex; + + @Setup(Level.Trial) + public void setUp() { + DummyEnum[] values = DummyEnum.values(); + for (int i = 0; i < len; i++) { + enumMap.put(values[i], values[i].toString()); + hashMap.put(values[i], values[i].toString()); + treeMap.put(values[i], values[i].toString()); + } + } + + @Setup(Level.Invocation) + public void additionalSetup() { + randomIndex = random.nextInt(len); + } + + } + + @Benchmark + public int benchmark01_EnumMapPut(BenchmarkState s) { + s.enumMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark01_HashMapPut(BenchmarkState s) { + s.hashMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark01_TreeMapPut(BenchmarkState s) { + s.treeMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_EnumMapGet(BenchmarkState s) { + s.enumMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_HashMapGet(BenchmarkState s) { + s.hashMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_TreeMapGet(BenchmarkState s) { + s.treeMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_EnumMapContainsKey(BenchmarkState s) { + s.enumMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_HashMapContainsKey(BenchmarkState s) { + s.hashMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_TreeMapContainsKey(BenchmarkState s) { + s.treeMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_EnumMapContainsValue(BenchmarkState s) { + s.enumMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_HashMapContainsValue(BenchmarkState s) { + s.hashMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_TreeMapContainsValue(BenchmarkState s) { + s.treeMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder().include(EnumMapBenchmarkLiveTest.class.getSimpleName()).threads(1).forks(0).shouldFailOnError(true).shouldDoGC(false).jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapUnitTest.java new file mode 100644 index 0000000000..80e8273a39 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/enummap/EnumMapUnitTest.java @@ -0,0 +1,144 @@ +package com.ossez.enummap; + +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static java.util.AbstractMap.SimpleEntry; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +public class EnumMapUnitTest { + public enum DayOfWeek { + MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY + } + + @Test + public void whenContructedWithEnumType_ThenOnlyAcceptThatAsKey() { + Map dayMap = new EnumMap<>(DayOfWeek.class); + assertThatCode( + () -> dayMap.put(TimeUnit.NANOSECONDS, "NANOSECONDS")) + .isInstanceOf(ClassCastException.class); + } + + @Test + public void whenConstructedWithEnumMap_ThenSameKeyTypeAndInitialMappings() { + EnumMap activityMap = new EnumMap<>(DayOfWeek.class); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + activityMap.put(DayOfWeek.TUESDAY, "Basketball"); + + EnumMap activityMapCopy = new EnumMap<>(activityMap); + assertThat(activityMapCopy.size()).isEqualTo(2); + assertThat(activityMapCopy.get(DayOfWeek.MONDAY)) + .isEqualTo("Soccer"); + assertThat(activityMapCopy.get(DayOfWeek.TUESDAY)) + .isEqualTo("Basketball"); + } + + @Test + public void givenEmptyMap_whenConstructedWithMap_ThenException() { + HashMap ordinaryMap = new HashMap(); + assertThatCode(() -> new EnumMap(ordinaryMap)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Specified map is empty"); + } + + @Test + public void givenMapWithEntries_whenConstructedWithMap_ThenSucceed() { + HashMap ordinaryMap = new HashMap<>(); + ordinaryMap.put(DayOfWeek.MONDAY, "Soccer"); + ordinaryMap.put(DayOfWeek.TUESDAY, "Basketball"); + EnumMap enumMap = new EnumMap<>(ordinaryMap); + assertThat(enumMap.size()).isEqualTo(2); + assertThat(enumMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer"); + assertThat(enumMap.get(DayOfWeek.TUESDAY)).isEqualTo("Basketball"); + } + + @Test + public void givenMapWithMultiTypeEntries_whenConstructedWithMap_ThenException() { + HashMap ordinaryMap = new HashMap<>(); + ordinaryMap.put(DayOfWeek.MONDAY, "Soccer"); + ordinaryMap.put(TimeUnit.MILLISECONDS, "Other enum type"); + assertThatCode(() -> new EnumMap(ordinaryMap)) + .isInstanceOf(ClassCastException.class); + } + + @Test + public void whenPut_thenGet() { + Map activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.THURSDAY, null); + assertThat(activityMap.get(DayOfWeek.WEDNESDAY)).isEqualTo("Hiking"); + assertThat(activityMap.get(DayOfWeek.THURSDAY)).isNull(); + } + + @Test + public void givenMapping_whenContains_thenTrue() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse(); + assertThat(activityMap.containsValue("Hiking")).isFalse(); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isTrue(); + assertThat(activityMap.containsValue("Hiking")).isTrue(); + + assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isFalse(); + assertThat(activityMap.containsValue(null)).isFalse(); + activityMap.put(DayOfWeek.SATURDAY, null); + assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isTrue(); + assertThat(activityMap.containsValue(null)).isTrue(); + } + + @Test + public void whenRemove_thenRemoved() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + assertThat(activityMap.remove(DayOfWeek.MONDAY)).isEqualTo("Soccer"); + assertThat(activityMap.containsKey(DayOfWeek.MONDAY)).isFalse(); + + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + assertThat(activityMap.remove(DayOfWeek.MONDAY, "Hiking")).isEqualTo(false); + assertThat(activityMap.remove(DayOfWeek.MONDAY, "Soccer")).isEqualTo(true); + } + + @Test + public void whenSubView_thenSubViewOrdered() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.THURSDAY, "Karate"); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + + Collection values = activityMap.values(); + assertThat(values).containsExactly("Soccer", "Hiking", "Karate"); + + Set keys = activityMap.keySet(); + assertThat(keys) + .containsExactly(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY,DayOfWeek.THURSDAY); + + assertThat(activityMap.entrySet()) + .containsExactly( + new SimpleEntry(DayOfWeek.MONDAY, "Soccer"), + new SimpleEntry(DayOfWeek.WEDNESDAY, "Hiking"), + new SimpleEntry(DayOfWeek.THURSDAY, "Karate")); + } + + @Test + public void givenSubView_whenChange_thenReflected() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.THURSDAY, "Karate"); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + + Collection values = activityMap.values(); + assertThat(values).containsExactly("Soccer", "Hiking", "Karate"); + + activityMap.put(DayOfWeek.TUESDAY, "Basketball"); + assertThat(values) + .containsExactly("Soccer", "Basketball", "Hiking", "Karate"); + + values.remove("Hiking"); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse(); + assertThat(activityMap.size()).isEqualTo(3); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/hashtable/HashtableUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/hashtable/HashtableUnitTest.java new file mode 100644 index 0000000000..7e83b5af47 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/hashtable/HashtableUnitTest.java @@ -0,0 +1,274 @@ +package com.ossez.hashtable; + +import java.util.ConcurrentModificationException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import org.junit.Test; + +public class HashtableUnitTest { + + @Test + public void whenPutAndGet_thenReturnsValue() { + Hashtable table = new Hashtable(); + + Word word = new Word("cat"); + table.put(word, "an animal"); + + String definition = table.get(word); + + assertEquals("an animal", definition); + + definition = table.remove(word); + + assertEquals("an animal", definition); + } + + @Test + public void whenThesameInstanceOfKey_thenReturnsValue() { + Hashtable table = new Hashtable(); + Word word = new Word("cat"); + table.put(word, "an animal"); + String extracted = table.get(word); + assertEquals("an animal", extracted); + } + + @Test + public void whenEqualsOverridden_thenReturnsValue() { + Hashtable table = new Hashtable(); + Word word = new Word("cat"); + table.put(word, "an animal"); + String extracted = table.get(new Word("cat")); + assertEquals("an animal", extracted); + } + + @Test(expected = NullPointerException.class) + public void whenNullKey_thenException() { + Hashtable table = new Hashtable(); + table.put(null, "an animal"); + } + + @Test(expected = ConcurrentModificationException.class) + public void whenIterate_thenFailFast() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "an animal"); + table.put(new Word("dog"), "another animal"); + + Iterator it = table.keySet().iterator(); + System.out.println("iterator created"); + + table.remove(new Word("dog")); + System.out.println("element removed"); + + while (it.hasNext()) { + Word key = it.next(); + System.out.println(table.get(key)); + } + } + + @Test + public void whenEnumerate_thenNotFailFast() { + + Hashtable table = new Hashtable(); + table.put(new Word("1"), "one"); + table.put(new Word("2"), "two"); + table.put(new Word("3"), "three"); + table.put(new Word("4"), "four"); + table.put(new Word("5"), "five"); + table.put(new Word("6"), "six"); + table.put(new Word("7"), "seven"); + table.put(new Word("8"), "eight"); + + Enumeration enumKey = table.keys(); + System.out.println("Enumeration created"); + table.remove(new Word("1")); + System.out.println("element removed"); + while (enumKey.hasMoreElements()) { + Word key = enumKey.nextElement(); + System.out.println(table.get(key)); + } + } + + @Test + public void whenAddElements_thenIterationOrderUnpredicable() { + + Hashtable table = new Hashtable(); + table.put(new Word("1"), "one"); + table.put(new Word("2"), "two"); + table.put(new Word("3"), "three"); + table.put(new Word("4"), "four"); + table.put(new Word("5"), "five"); + table.put(new Word("6"), "six"); + table.put(new Word("7"), "seven"); + table.put(new Word("8"), "eight"); + + Iterator> it = table.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + System.out.println(entry.getValue()); + } + } + + @Test + public void whenGetOrDefault_thenDefaultGot() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + Word key = new Word("dog"); + String definition; + + // old way + /* if (table.containsKey(key)) { + definition = table.get(key); + } else { + definition = "not found"; + }*/ + + // new way + definition = table.getOrDefault(key, "not found"); + + assertThat(definition, is("not found")); + } + + @Test + public void whenPutifAbsent_thenNotRewritten() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + + String definition = "an animal"; + // old way + /* if (!table.containsKey(new Word("cat"))) { + table.put(new Word("cat"), definition); + }*/ + // new way + table.putIfAbsent(new Word("cat"), definition); + + assertThat(table.get(new Word("cat")), is("a small domesticated carnivorous mammal")); + } + + @Test + public void whenRemovePair_thenCheckKeyAndValue() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + + // old way + /* if (table.get(new Word("cat")).equals("an animal")) { + table.remove(new Word("cat")); + }*/ + + // new way + boolean result = table.remove(new Word("cat"), "an animal"); + + assertThat(result, is(false)); + } + + @Test + public void whenReplacePair_thenValueChecked() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + + String definition = "an animal"; + + // old way + /* if (table.containsKey(new Word("cat")) && table.get(new Word("cat")).equals("a small domesticated carnivorous mammal")) { + table.put(new Word("cat"), definition); + }*/ + // new way + table.replace(new Word("cat"), "a small domesticated carnivorous mammal", definition); + + assertThat(table.get(new Word("cat")), is("an animal")); + + } + + @Test + public void whenKeyIsAbsent_thenNotRewritten() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + + // old way + /* if (!table.containsKey(cat)) { + String definition = "an animal";// calculate + table.put(new Word("cat"), definition); + } + */ + // new way + + table.computeIfAbsent(new Word("cat"), key -> "an animal"); + assertThat(table.get(new Word("cat")), is("a small domesticated carnivorous mammal")); + + } + + @Test + public void whenKeyIsPresent_thenComputeIfPresent() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + + Word cat = new Word("cat"); + // old way + /* if (table.containsKey(cat)) { + String concatination = cat.getName() + " - " + table.get(cat); + table.put(cat, concatination); + }*/ + + // new way + table.computeIfPresent(cat, (key, value) -> key.getName() + " - " + value); + + assertThat(table.get(cat), is("cat - a small domesticated carnivorous mammal")); + + } + + @Test + public void whenCompute_thenForAllKeys() { + + Hashtable table = new Hashtable(); + String[] animals = { "cat", "dog", "dog", "cat", "bird", "mouse", "mouse" }; + for (String animal : animals) { + table.compute(animal, (key, value) -> (value == null ? 1 : value + 1)); + } + assertThat(table.values(), hasItems(2, 2, 2, 1)); + + } + + @Test + public void whenInsteadOfCompute_thenMerge() { + + Hashtable table = new Hashtable(); + String[] animals = { "cat", "dog", "dog", "cat", "bird", "mouse", "mouse" }; + for (String animal : animals) { + table.merge(animal, 1, (oldValue, value) -> (oldValue + value)); + } + assertThat(table.values(), hasItems(2, 2, 2, 1)); + } + + @Test + public void whenForeach_thenIterate() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + table.put(new Word("dog"), "another animal"); + table.forEach((k, v) -> System.out.println(k.getName() + " - " + v) + + ); + } + + @Test + public void whenReplaceall_thenNoIterationNeeded() { + + Hashtable table = new Hashtable(); + table.put(new Word("cat"), "a small domesticated carnivorous mammal"); + table.put(new Word("dog"), "another animal"); + table.replaceAll((k, v) -> k.getName() + " - " + v); + + assertThat(table.values(), hasItems("cat - a small domesticated carnivorous mammal", "dog - another animal")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/CustomBaeldungQueueUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/CustomBaeldungQueueUnitTest.java new file mode 100644 index 0000000000..e57127aa49 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/CustomBaeldungQueueUnitTest.java @@ -0,0 +1,30 @@ +package com.ossez.queueInterface; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CustomBaeldungQueueUnitTest { + + private CustomBaeldungQueue customQueue; + + @Before + public void setUp() throws Exception { + customQueue = new CustomBaeldungQueue<>(); + } + + @Test + public void givenQueueWithTwoElements_whenElementsRetrieved_checkRetrievalCorrect() { + + customQueue.add(7); + customQueue.add(5); + + int first = customQueue.poll(); + int second = customQueue.poll(); + + assertEquals(7, first); + assertEquals(5, second); + + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/PriorityQueueUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/PriorityQueueUnitTest.java new file mode 100644 index 0000000000..6313ec1952 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/queueInterface/PriorityQueueUnitTest.java @@ -0,0 +1,53 @@ +package com.ossez.queueInterface; + +import org.junit.Before; +import org.junit.Test; + +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +public class PriorityQueueUnitTest { + + + + @Test + public void givenIntegerQueue_whenIntegersOutOfOrder_checkRetrievalOrderIsNatural() { + + PriorityQueue integerQueue = new PriorityQueue<>(); + + integerQueue.add(9); + integerQueue.add(2); + integerQueue.add(4); + + int first = integerQueue.poll(); + int second = integerQueue.poll(); + int third = integerQueue.poll(); + + assertEquals(2, first); + assertEquals(4, second); + assertEquals(9, third); + + + } + + @Test + public void givenStringQueue_whenStringsAddedOutOfNaturalOrder_checkRetrievalOrderNatural() { + + PriorityQueue stringQueue = new PriorityQueue<>(); + + stringQueue.add("banana"); + stringQueue.add("apple"); + stringQueue.add("cherry"); + + String first = stringQueue.poll(); + String second = stringQueue.poll(); + String third = stringQueue.poll(); + + assertEquals("apple", first); + assertEquals("banana", second); + assertEquals("cherry", third); + + + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/MultithreadingCorrectnessStackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/MultithreadingCorrectnessStackUnitTest.java new file mode 100644 index 0000000000..f9f2a7e33a --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/MultithreadingCorrectnessStackUnitTest.java @@ -0,0 +1,101 @@ +package com.ossez.stack_tests; + +import com.ossez.thread_safe_lifo.DequeBasedSynchronizedStack; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.concurrent.ConcurrentLinkedDeque; + +import static java.util.stream.IntStream.range; + +/** + * Correctness tests for Stack in multi threaded environment. + */ +public class MultithreadingCorrectnessStackUnitTest { + + @Test + public void givenSynchronizedDeque_whenExecutedParallel_thenWorkRight() { + + DequeBasedSynchronizedStack deque = new DequeBasedSynchronizedStack<>(); + + // Serial execution of push on ConcurrentLinkedQueue will always result in correct execution. + range(1, 10000).forEach(value -> deque.push(value)); + + int sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + Assert.assertEquals(49995000, sum); + + // Parallel execution of push on ConcurrentLinkedQueue will always result in correct execution. + range(1, 10000).parallel().forEach(value -> deque.push(value)); + + sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + Assert.assertEquals(49995000, sum); + } + + @Test + public void givenConcurrentLinkedQueue_whenExecutedParallel_thenWorkRight() { + + ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>(); + + // Serial execution of push on ConcurrentLinkedQueue will always result in correct execution. + range(1, 10000).forEach(value -> deque.push(value)); + + int sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + Assert.assertEquals(49995000, sum); + + // Parallel execution of push on ConcurrentLinkedQueue will always result in correct execution. + range(1, 10000).parallel().forEach(value -> deque.push(value)); + + sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + Assert.assertEquals(49995000, sum); + } + + @Test + public void givenArrayDeque_whenExecutedParallel_thenShouldFail() { + + ArrayDeque deque = new ArrayDeque<>(); + + // Serial execution of push on ArrayDeque will always result in correct execution. + range(1, 10000).forEach(value -> deque.push(value)); + + int sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + Assert.assertEquals(49995000, sum); + + // Parallel execution of push on ArrayDeque will not result in correct execution. + range(1, 10000).parallel().forEach(value -> deque.push(value)); + + sum = 0; + while(deque.peek() != null) { + sum += deque.pop(); + } + + // This shouldn't happen. + if(sum == 49995000) { + System.out.println("Something wrong in the environment, Please try some big value and check"); + // To safe-guard build without test failures. + return; + } + + Assert.assertNotEquals(49995000, sum); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/StackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/StackUnitTest.java new file mode 100644 index 0000000000..2df7c9f0f0 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/stack_tests/StackUnitTest.java @@ -0,0 +1,56 @@ +package com.ossez.stack_tests; + +import com.ossez.thread_safe_lifo.DequeBasedSynchronizedStack; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Stack; +import java.util.concurrent.ConcurrentLinkedDeque; + +/** + * These tests are to understand the Stack implementation in Java Collections. + */ +public class StackUnitTest { + + @Test + public void givenStack_whenPushPopPeek_thenWorkRight() { + Stack namesStack = new Stack<>(); + + namesStack.push("Bill Gates"); + namesStack.push("Elon Musk"); + + Assert.assertEquals("Elon Musk", namesStack.peek()); + Assert.assertEquals("Elon Musk", namesStack.pop()); + Assert.assertEquals("Bill Gates", namesStack.pop()); + + Assert.assertEquals(0, namesStack.size()); + } + + @Test + public void givenSynchronizedDeque_whenPushPopPeek_thenWorkRight() { + DequeBasedSynchronizedStack namesStack = new DequeBasedSynchronizedStack<>(); + + namesStack.push("Bill Gates"); + namesStack.push("Elon Musk"); + + Assert.assertEquals("Elon Musk", namesStack.peek()); + Assert.assertEquals("Elon Musk", namesStack.pop()); + Assert.assertEquals("Bill Gates", namesStack.pop()); + + Assert.assertEquals(0, namesStack.size()); + } + + @Test + public void givenConcurrentLinkedDeque_whenPushPopPeek_thenWorkRight() { + ConcurrentLinkedDeque namesStack = new ConcurrentLinkedDeque<>(); + + namesStack.push("Bill Gates"); + namesStack.push("Elon Musk"); + + Assert.assertEquals("Elon Musk", namesStack.peek()); + Assert.assertEquals("Elon Musk", namesStack.pop()); + Assert.assertEquals("Bill Gates", namesStack.pop()); + + Assert.assertEquals(0, namesStack.size()); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedCollectionUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedCollectionUnitTest.java new file mode 100644 index 0000000000..f3b6f73995 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedCollectionUnitTest.java @@ -0,0 +1,28 @@ +package com.ossez.synchronizedcollections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedCollectionUnitTest { + + @Test + public void givenSynchronizedCollection_whenTwoThreadsAddElements_thenCorrectCollectionSize() throws InterruptedException { + Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>()); + + Runnable listOperations = () -> { + syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); + }; + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncCollection.size()).isEqualTo(12); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedListUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedListUnitTest.java new file mode 100644 index 0000000000..8c6d0df831 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedListUnitTest.java @@ -0,0 +1,51 @@ +package com.ossez.synchronizedcollections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedListUnitTest { + + @Test + public void givenSynchronizedList_whenTwoThreadsAddElements_thenCorrectListSize() throws InterruptedException { + List syncList = Collections.synchronizedList(new ArrayList<>()); + + Runnable listOperations = () -> { + syncList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); + }; + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncList.size()).isEqualTo(12); + } + + @Test + public void givenStringList_whenTwoThreadsIterateOnSynchronizedList_thenCorrectResult() throws InterruptedException { + List syncCollection = Collections.synchronizedList(Arrays.asList("a", "b", "c")); + List uppercasedCollection = new ArrayList<>(); + + Runnable listOperations = () -> { + synchronized (syncCollection) { + syncCollection.forEach((e) -> { + uppercasedCollection.add(e.toUpperCase()); + }); + } + }; + + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(uppercasedCollection.get(0)).isEqualTo("A"); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedMapUnitTest.java new file mode 100644 index 0000000000..b543c9ac1b --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedMapUnitTest.java @@ -0,0 +1,30 @@ +package com.ossez.synchronizedcollections; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedMapUnitTest { + + @Test + public void givenSynchronizedMap_whenTwoThreadsAddElements_thenCorrectMapSize() throws InterruptedException { + Map syncMap = Collections.synchronizedMap(new HashMap<>()); + + Runnable mapOperations = () -> { + syncMap.put(1, "one"); + syncMap.put(2, "two"); + syncMap.put(3, "three"); + + }; + Thread thread1 = new Thread(mapOperations); + Thread thread2 = new Thread(mapOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncMap.size()).isEqualTo(3); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSetUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSetUnitTest.java new file mode 100644 index 0000000000..cb1be80114 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSetUnitTest.java @@ -0,0 +1,26 @@ +package com.ossez.synchronizedcollections; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedSetUnitTest { + + @Test + public void givenSynchronizedSet_whenTwoThreadsAddElements_thenCorrectSetSize() throws InterruptedException { + Set syncSet = Collections.synchronizedSet(new HashSet<>()); + + Runnable setOperations = () -> {syncSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; + Thread thread1 = new Thread(setOperations); + Thread thread2 = new Thread(setOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSet.size()).isEqualTo(6); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedMapUnitTest.java new file mode 100644 index 0000000000..a3124a7005 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedMapUnitTest.java @@ -0,0 +1,29 @@ +package com.ossez.synchronizedcollections; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedSortedMapUnitTest { + + @Test + public void givenSynchronizedSorteMap_whenTwoThreadsAddElements_thenCorrectSortedMapSize() throws InterruptedException { + Map syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>()); + + Runnable sortedMapOperations = () -> { + syncSortedMap.put(1, "One"); + syncSortedMap.put(2, "Two"); + syncSortedMap.put(3, "Three"); + }; + Thread thread1 = new Thread(sortedMapOperations); + Thread thread2 = new Thread(sortedMapOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSortedMap.size()).isEqualTo(3); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedSetUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedSetUnitTest.java new file mode 100644 index 0000000000..1877bebc52 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/ossez/synchronizedcollections/SynchronizedSortedSetUnitTest.java @@ -0,0 +1,28 @@ +package com.ossez.synchronizedcollections; + +import java.util.Arrays; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedSortedSetUnitTest { + + @Test + public void givenSynchronizedSortedSet_whenTwoThreadsAddElements_thenCorrectSortedSetSize() throws InterruptedException { + SortedSet syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>()); + + Runnable sortedSetOperations = () -> {syncSortedSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; + sortedSetOperations.run(); + sortedSetOperations.run(); + Thread thread1 = new Thread(sortedSetOperations); + Thread thread2 = new Thread(sortedSetOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSortedSet.size()).isEqualTo(6); + } +}