0% found this document useful (0 votes)
18 views11 pages

Advanced Java Programming Exercises

The document contains a series of advanced Java exercises, each with a question and corresponding implementation. Topics include thread-safe data structures, stream operations, producer-consumer patterns, and algorithms for string manipulation and number processing. Each exercise is accompanied by code snippets demonstrating the solution.

Uploaded by

my.misk
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views11 pages

Advanced Java Programming Exercises

The document contains a series of advanced Java exercises, each with a question and corresponding implementation. Topics include thread-safe data structures, stream operations, producer-consumer patterns, and algorithms for string manipulation and number processing. Each exercise is accompanied by code snippets demonstrating the solution.

Uploaded by

my.misk
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Set 3: Advanced Java Exercises

1. Question: Implement a thread-safe counter using AtomicInteger.​


Answer:

import [Link];

public class AtomicCounter {


private static AtomicInteger counter = new AtomicInteger(0);

public static void main(String[] args) throws


InterruptedException {
Runnable task = () -> {
for(int i=0;i<1000;i++) [Link]();
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
[Link](); [Link]();
[Link](); [Link]();
[Link]("Counter: " + [Link]());
}
}

2. Question: Write a program to filter a list of strings that start


with a vowel using streams.​
Answer:

import [Link].*;
import [Link].*;

public class FilterVowel {


public static void main(String[] args) {
List<String> words = [Link]("apple", "banana",
"orange", "umbrella", "grape");
List<String> result = [Link]()
.filter(w ->
[Link]("^[aeiouAEIOU].*"))
.collect([Link]());
[Link](result);
}
}
3. Question: Implement a Java program to calculate the sum of
integers in a list using reduce().​
Answer:

import [Link].*;
import [Link].*;

public class SumReduce {


public static void main(String[] args) {
List<Integer> nums = [Link](1,2,3,4,5);
int sum = [Link]().reduce(0, Integer::sum);
[Link](sum);
}
}

4. Question: Write a program to implement a producer-consumer using


Semaphore.​
Answer:

import [Link].*;

public class SemaphorePC {


private static Semaphore empty = new Semaphore(5);
private static Semaphore full = new Semaphore(0);
private static int count = 0;

public static void main(String[] args) {


Runnable producer = () -> {
try {
for(int i=0;i<10;i++) {
[Link]();
count++;
[Link]("Produced: " + count);
[Link]();
}
} catch(Exception e) {}
};

Runnable consumer = () -> {


try {
for(int i=0;i<10;i++) {
[Link]();
[Link]("Consumed: " + count);
count--;
[Link]();
}
} catch(Exception e) {}
};
new Thread(producer).start();
new Thread(consumer).start();
}
}

5. Question: Implement a program to find all permutations of a


string.​
Answer:

public class StringPermutations {


public static void permute(String str, String prefix) {
if([Link]()) [Link](prefix);
for(int i=0;i<[Link]();i++)
permute([Link](0,i)+[Link](i+1),
prefix+[Link](i));
}

public static void main(String[] args) {


permute("ABC", "");
}
}

6. Question: Write a Java program to implement a producer-consumer


problem with multiple producers and consumers.​
Answer:

import [Link].*;

public class MultiPC {


public static void main(String[] args) {
BlockingQueue<Integer> queue = new
ArrayBlockingQueue<>(5);
Runnable producer = () -> {
for(int i=0;i<10;i++){
try { [Link](i); [Link]("Produced:
"+i); }
catch(InterruptedException e) {}
}
};
Runnable consumer = () -> {
for(int i=0;i<10;i++){
try { int val = [Link]();
[Link]("Consumed: "+val); }
catch(InterruptedException e) {}
}
};
new Thread(producer).start();
new Thread(producer).start();
new Thread(consumer).start();
new Thread(consumer).start();
}
}

7. Question: Implement a program to flatten a


Map<String,List<Integer>> into a list of integers.​
Answer:

import [Link].*;
import [Link].*;

public class FlattenMap {


public static void main(String[] args) {
Map<String, List<Integer>> map = new HashMap<>();
[Link]("A", [Link](1,2));
[Link]("B", [Link](3,4));
List<Integer> flat = [Link]().stream()
.flatMap(List::stream)
.collect([Link]());
[Link](flat);
}
}

8. Question: Write a program to implement a binary search tree


insertion and in-order traversal.​
Answer:

class Node {
int val; Node left,right;
Node(int val){ [Link]=val; }
}

public class BST {


Node root;
void insert(int val) { root = insertRec(root,val); }
Node insertRec(Node root,int val){
if(root==null) return new Node(val);
if(val<[Link]) [Link] = insertRec([Link],val);
else [Link] = insertRec([Link],val);
return root;
}
void inorder(Node root){
if(root!=null){
inorder([Link]);
[Link]([Link]+" ");
inorder([Link]);
}
}
public static void main(String[] args){
BST tree = new BST();
[Link](5); [Link](3); [Link](7);
[Link](1);
[Link]([Link]);
}
}

9. Question: Implement a program to filter out prime numbers from a


list using streams.​
Answer:

import [Link].*;
import [Link].*;

public class PrimeFilter {


static boolean isPrime(int n){
if(n<2) return false;
for(int i=2;i*i<=n;i++) if(n%i==0) return false;
return true;
}

public static void main(String[] args){


List<Integer> nums = [Link](1,2,3,4,5,6,7);
List<Integer> primes =
[Link]().filter(PrimeFilter::isPrime).collect([Link]
st());
[Link](primes);
}
}

10. Question: Write a program to implement a singleton using an


enum.​
Answer:

enum SingletonEnum {
INSTANCE;
public void show() { [Link]("Singleton using
Enum"); }
}

public class MainEnum {


public static void main(String[] args){
[Link]();
}
}

11. Question: Implement a Java program to group a list of strings


by their length using streams.​
Answer:

import [Link].*;
import [Link].*;

public class GroupByLength {


public static void main(String[] args) {
List<String> words = [Link]("Java", "Stream",
"API", "Collections", "Code");
Map<Integer, List<String>> grouped = [Link]()

.collect([Link](String::length));
[Link](grouped);
}
}

12. Question: Write a program to implement a thread-safe stack


using ReentrantLock.​
Answer:

import [Link].*;
import [Link].*;

class ThreadSafeStack<T> {
private Stack<T> stack = new Stack<>();
private Lock lock = new ReentrantLock();

public void push(T item) {


[Link]();
try { [Link](item); }
finally { [Link](); }
}

public T pop() {
[Link]();
try { return [Link](); }
finally { [Link](); }
}
}

public class MainStack {


public static void main(String[] args) {
ThreadSafeStack<Integer> stack = new ThreadSafeStack<>();
[Link](1); [Link](2);
[Link]([Link]());
}
}

13. Question: Implement a program to find the longest palindrome


substring in a string.​
Answer:

public class LongestPalindrome {


public static String longestPalindrome(String s) {
int start=0, end=0;
for(int i=0;i<[Link]();i++){
int len1 = expandAroundCenter(s,i,i);
int len2 = expandAroundCenter(s,i,i+1);
int len = [Link](len1,len2);
if(len > end-start){
start = i-(len-1)/2;
end = i+len/2;
}
}
return [Link](start,end+1);
}

private static int expandAroundCenter(String s,int left,int


right){
while(left>=0 && right<[Link]() &&
[Link](left)==[Link](right)){
left--; right++;
}
return right-left-1;
}

public static void main(String[] args){


String str = "babad";
[Link](longestPalindrome(str));
}
}
14. Question: Write a program to implement a scheduled task using
ScheduledExecutorService.​
Answer:

import [Link].*;

public class ScheduledTaskDemo {


public static void main(String[] args){
ScheduledExecutorService scheduler =
[Link](1);
Runnable task = () -> [Link]("Task executed
at: " + [Link]());
[Link](task, 0, 2,
[Link]);
}
}

15. Question: Implement a program to find duplicate characters in a


string using streams.​
Answer:

import [Link].*;
import [Link].*;

public class DuplicateChars {


public static void main(String[] args){
String str = "programming";
Map<Character, Long> freq = [Link]()
.mapToObj(c -> (char)c)

.collect([Link](c -> c, [Link]()));


[Link]().stream()
.filter(e -> [Link]() > 1)
.forEach([Link]::println);
}
}

16. Question: Write a program to implement a countdown latch.​


Answer:

import [Link].*;

public class CountdownLatchDemo {


public static void main(String[] args) throws
InterruptedException{
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
[Link]([Link]().getName() +
" finished");
[Link]();
};
new Thread(task,"Thread-1").start();
new Thread(task,"Thread-2").start();
new Thread(task,"Thread-3").start();
[Link]();
[Link]("All threads finished");
}
}

17. Question: Implement a program to rotate an array by k


positions.​
Answer:

import [Link].*;

public class RotateArray {


public static void main(String[] args){
int[] arr = {1,2,3,4,5};
int k = 2;
int n = [Link];
int[] rotated = new int[n];
for(int i=0;i<n;i++){
rotated[(i+k)%n] = arr[i];
}
[Link]([Link](rotated));
}
}

18. Question: Write a program to implement a simple cache using


LinkedHashMap with access order.​
Answer:

import [Link].*;

class LRUCache<K,V> extends LinkedHashMap<K,V> {


private int capacity;
LRUCache(int capacity){
super(capacity, 0.75f, true);
[Link] = capacity;
}
protected boolean removeEldestEntry([Link]<K,V> eldest){
return size() > capacity;
}
}
public class MainCache {
public static void main(String[] args){
LRUCache<Integer,String> cache = new LRUCache<>(3);
[Link](1,"A"); [Link](2,"B"); [Link](3,"C");
[Link](1);
[Link](4,"D");
[Link](cache);
}
}

19. Question: Implement a program to find the missing number in an


array of 1 to N.​
Answer:

public class MissingNumber {


public static void main(String[] args){
int[] arr = {1,2,4,5,6};
int n = 6;
int expected = n*(n+1)/2;
int sum = 0;
for(int num : arr) sum += num;
[Link]("Missing: " + (expected - sum));
}
}

20. Question: Write a program to implement a producer-consumer


problem using BlockingQueue with multiple consumers.​
Answer:

import [Link].*;

public class MultiConsumerPC {


public static void main(String[] args){
BlockingQueue<Integer> queue = new
ArrayBlockingQueue<>(5);
Runnable producer = () -> {
for(int i=0;i<10;i++){
try { [Link](i); [Link]("Produced:
"+i); }
catch(InterruptedException e) {}
}
};
Runnable consumer = () -> {
for(int i=0;i<5;i++){
try { int val = [Link]();
[Link]([Link]().getName() + " Consumed:
"+val); }
catch(InterruptedException e) {}
}
};
new Thread(producer).start();
new Thread(consumer,"Consumer-1").start();
new Thread(consumer,"Consumer-2").start();
}
}

Common questions

Powered by AI

AtomicInteger can be used to implement a thread-safe counter in Java by providing atomic operations on integers that can be used without explicit synchronization. The main advantage of AtomicInteger over traditional synchronization techniques like synchronized blocks is that it avoids blocking threads, which can lead to performance improvements in highly concurrent environments. Using AtomicInteger, operations like incrementing a counter are performed atomically, meaning they execute completely without interruption, ensuring that updates from different threads do not overlap .

CountdownLatch is chosen over other synchronization constructs in Java applications primarily for its simplicity in scenarios where a thread needs to wait until several other threads have completed their execution tasks. It is commonly used for scenarios that involve orchestrating multiple threads to wait for a common resource setup or to trigger execution once all prerequisites are available. Unlike CyclicBarrier, which can be reused, CountdownLatch is a one-time synchronization aid that fits well in the context where the waiting strategy does not require reuse. Its primary use cases include starting services in a specific order, testing multi-threaded applications, and controlling start and stop conditions for groups of threads .

ReentrantLock plays a critical role in implementing a thread-safe stack by providing a more flexible locking mechanism compared to synchronized blocks. Unlike synchronized blocks, ReentrantLock allows more control over the lock, with features including lock polling, timed lock waits, and interruptible lock waits. This can improve responsiveness and performance in certain scenarios where locks are expected to be contested. Additionally, ReentrantLocks can be released in a different block than the one in which they were acquired, offering greater flexibility in managing lock acquisition and release .

Using Java streams for grouping strings by their length is highly effective in terms of code readability and maintainability. The syntax allows developers to express grouping operations concisely with clear abstraction, reducing boilerplate code compared to traditional iteration approaches. In terms of performance, Java streams can take advantage of parallel processing, which may improve performance in large-scale applications. However, in small datasets, there might be no significant performance benefit, and traditional loops might be faster due to the overhead of stream processing. Overall, streams provide a more elegant solution for grouping tasks while maintaining solid performance for moderate to large datasets .

Binary search tree operations in Java can be performed by defining a Node class with value, left, and right pointers to embody tree nodes. Insertion is done through recursion, placing elements based on comparison (lesser values to the left, greater to the right) to maintain tree order. In-order traversal follows a structured recursion: visit the left subtree, node, then right subtree, which outputs elements in sorted order. Applications of binary search trees include providing logarithmic search complexity for data retrieval, serving as a foundational structure for more complex search algorithms, and implementing associative arrays and set data types .

The technique involved in finding the longest palindrome substring using the expand-around-center approach entails iterating over each character and its neighboring pairs in the string, treating each as potential centers of a palindrome. For every center, two pointers expand outward as long as they encounter equal characters, checking each possible substring. This expansion calculates the longest palindrome by comparing lengths, updating the maximum length and relevant indices for substring extraction. This approach is efficient due to its focus on potential palindrome centers and direct expansion, resulting in a time complexity of O(n^2).

Using LinkedHashMap to implement a simple cache system with access order has several benefits and limitations. The main benefit is that LinkedHashMap, when configured with access order, maintains the order of entries based on read operations, allowing for easy implementation of LRU (Least Recently Used) caching by removing the oldest entry when the cache exceeds its capacity. Additionally, it's straightforward to implement and offers O(1) complexity for get and put operations. However, the primary limitation is that LinkedHashMap is not thread-safe, and thus not suitable for concurrent access without external synchronization. Furthermore, its memory usage could be higher than simpler structures like arrays due to the underlying linked structure .

Implementing a singleton pattern using an enum in Java involves defining a single-element enum type where the instance is ensured by the JVM. This takes advantage of the inherent property of enums in Java, being declared once and thread-safe by the specification. The key advantage over classical methods, such as lazy instantiation holder classes or synchronized methods, is the guarantee against multiple instantiation due to Java's handling of enum singletons. Moreover, it simplifies serialization and defends against reflection attacks, ensuring only one instance is ever created and used throughout the application lifecycle .

Multithreading in Java can be achieved using Semaphore in the producer-consumer problem by managing access to shared resources with two semaphores: 'empty' to track remaining capacity and 'full' to indicate filled slots. Producers acquire the 'empty' semaphore before producing an item and release the 'full' semaphore after the item is produced. Conversely, consumers acquire the 'full' semaphore before consuming an item and release the 'empty' semaphore afterward. This synchronization ensures that producers wait if the buffer is full and consumers wait if it is empty, maintaining thread-safe operations without using blocking mechanisms inherent in synchronized blocks .

Java Streams can be utilized to filter a list of integers for prime numbers by following these steps: first, convert the integer list into a stream using stream(). Then, apply the filter method with a predicate that determines if a number is prime. This predicate can be a method reference or a lambda expression that checks divisibility for numbers greater than 1. Lastly, collect the filtered results into a new list using the collect method with Collectors.toList(). This approach leverages the isPrime method to efficiently filter primes from the stream .

You might also like