From 091ef2235d0917814f07b746e37593e9b688ea4f Mon Sep 17 00:00:00 2001 From: Senrian <47714364+Senrian@users.noreply.github.com> Date: Wed, 1 Apr 2026 08:34:02 +0800 Subject: [PATCH 1/2] fix(BinarySearch): add null key check to prevent NPE Issue #7356: Add null check for the search value to prevent potential NullPointerException. --- .../java/com/thealgorithms/searches/BinarySearch.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/searches/BinarySearch.java b/src/main/java/com/thealgorithms/searches/BinarySearch.java index 7a5361b280ea..ca873fc6eafa 100644 --- a/src/main/java/com/thealgorithms/searches/BinarySearch.java +++ b/src/main/java/com/thealgorithms/searches/BinarySearch.java @@ -58,11 +58,18 @@ class BinarySearch implements SearchAlgorithm { */ @Override public > int find(T[] array, T key) { - // Handle edge case: empty array + // Handle edge case: null or empty array if (array == null || array.length == 0) { return -1; } + // Handle edge case: null key + // Searching for null in an array of Comparables is undefined behavior + // Return -1 to indicate not found rather than throwing NPE + if (key == null) { + return -1; + } + // Delegate to the core search implementation return search(array, key, 0, array.length - 1); } From 91b762fdd347810a006bf679ad3ed6e31ceee539 Mon Sep 17 00:00:00 2001 From: Senrian <47714364+Senrian@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:24:54 +0800 Subject: [PATCH 2/2] Add ThreadSafeQueue implementation --- .../queues/ThreadSafeQueue.java | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/queues/ThreadSafeQueue.java diff --git a/src/main/java/com/thealgorithms/datastructures/queues/ThreadSafeQueue.java b/src/main/java/com/thealgorithms/datastructures/queues/ThreadSafeQueue.java new file mode 100644 index 000000000000..dee2fb11efbc --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/queues/ThreadSafeQueue.java @@ -0,0 +1,175 @@ +package com.thealgorithms.datastructures.queues; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A thread-safe queue implementation using a linked list with synchronized methods. + * This implementation uses the synchronized keyword to ensure thread safety. + * + * @param the type of elements held in this queue + */ +public final class ThreadSafeQueue implements Iterable { + + /** + * Node class representing each element in the queue. + */ + private static final class Node { + T data; + Node next; + + Node(T data) { + this.data = data; + this.next = null; + } + } + + private Node front; + private Node rear; + private int size; + + /** + * Initializes an empty ThreadSafeQueue. + */ + public ThreadSafeQueue() { + front = null; + rear = null; + size = 0; + } + + /** + * Checks if the queue is empty. + * + * @return true if the queue is empty, otherwise false + */ + public synchronized boolean isEmpty() { + return size == 0; + } + + /** + * Returns the size of the queue. + * + * @return the number of elements in the queue + */ + public synchronized int size() { + return size; + } + + /** + * Adds an element to the rear of the queue. + * + * @param data the element to insert + * @throws IllegalArgumentException if data is null + */ + public synchronized void enqueue(T data) { + if (data == null) { + throw new IllegalArgumentException("Cannot enqueue null data"); + } + + Node newNode = new Node<>(data); + + if (isEmpty()) { + front = newNode; + } else { + rear.next = newNode; + } + rear = newNode; + size++; + } + + /** + * Removes and returns the element at the front of the queue. + * + * @return the element at the front of the queue + * @throws NoSuchElementException if the queue is empty + */ + public synchronized T dequeue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + + T retValue = front.data; + front = front.next; + size--; + + if (isEmpty()) { + rear = null; + } + + return retValue; + } + + /** + * Returns the element at the front of the queue without removing it. + * + * @return the element at the front of the queue + * @throws NoSuchElementException if the queue is empty + */ + public synchronized T peek() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + return front.data; + } + + /** + * Returns an iterator over the elements in the queue. + * + * @return an iterator over the elements in the queue + */ + @Override + public synchronized Iterator iterator() { + return new Iterator<>() { + private Node current = front; + + @Override + public synchronized boolean hasNext() { + return current != null; + } + + @Override + public synchronized T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + T data = current.data; + current = current.next; + return data; + } + }; + } + + /** + * Clears all elements from the queue. + */ + public synchronized void clear() { + front = null; + rear = null; + size = 0; + } + + /** + * Returns a string representation of the queue. + * + * @return a string representation of the queue + */ + @Override + public synchronized String toString() { + if (isEmpty()) { + return "[]"; + } + + StringBuilder sb = new StringBuilder("["); + Node current = front; + while (current != null) { + sb.append(current.data); + if (current.next != null) { + sb.append(", "); + } + current = current.next; + } + sb.append(']'); + return sb.toString(); + } +}