You have a list of Employee objects having empNo,empName,gender,salary.
1a)Calculate the average salary of male employees using Java Streams.
1b) Filter male employees whose salary is greater than average salary
1c)Then save employee data into a CSV file in the format John,Male,50000.
1d) I want to sort the employee data based on name and then salary.
We have to create EmployeePOJO class.- Then we have use s
treamwithfilterandmapToDoublefollowed byaverage().
var and List.of() (Java 10+).Swamy,Male,50000, you can //use Files.write with a simple stream in Java-
filter: to select only male employees. -
mapToDouble: to extract salary. -
average(): returnsOptionalDouble. -
orElse(0.0): handles the case when no male employees are present.
a)Comparator.comparing(Employee::getEmpName) → sorts by name.b)thenComparing(Employee::getSalary) → if names are equal, sorts by salary.-------------------------------------
3) What is output? Why? explain correct version
Collectors.toList() should be used with .collect(...), not directly after .skip(...)..collect(...)) is called, the stream is consumed and cannot be used again.✅ Explanation:
-
alist.stream(): A new stream must be created each time because Java streams are single-use. -
.sorted().skip(4): Sorts the list and skips the first 4 elements. -
.collect(Collectors.toList()): Collects the resulting stream into aList.
4) What is the output for below?
String s1 ="abc";
String s2;//Some api call returning some value
if(s2==s1)
System.out.println("s1 and s2 are true");
s2.equals(s1);
❗ Issues:
-
s2is declared but never initialized:-
This will result in a compilation error: "variable s2 might not have been initialized."
-
-
Using
==to compare strings:-
==compares object references, not actual content. Use.equals()for content comparison.
-
-
Potential
NullPointerException:-
If
s2isnull, thens2.equals(s1)will throw a runtime error.
-
✅ Corrected Code:
✅ Safer Practice
๐ Null-safe string comparison:
This avoids NullPointerException if s2 is null, since the literal string "abc" is definitely not null.
๐งช Summary: String Comparison in Java
| Expression | What It Does |
|---|---|
s1 == s2 | Compares references (same memory address) |
s1.equals(s2) | Compares string contents |
"abc".equals(s2) | Null-safe content comparison |
Explanation:
๐ง What is .stream()?
stream() is a default method in the java.util.Collection interface that allows a collection (like List, Set, etc.) to produce a sequential Stream:
So when you call:
Internally, the above line actually invokes:
✅ Step 1: stream() in Collection Interface
Defined in java.util.Collection:
Here:
-
spliterator()is a method from theIterableinterface. -
falsemeans we want a sequential stream (not parallel).
✅ Step 2: spliterator() Method
Every collection provides its own implementation of spliterator().
For example:
A Spliterator is like a modern iterator with additional capabilities:
-
Can split the collection into parts (useful for parallel processing).
-
Supports characteristics like
SIZED,ORDERED, etc.
✅ Step 3: StreamSupport.stream(...)
From java.util.stream.StreamSupport:
๐ธ What is happening here?
-
The
stream()method constructs a pipeline starting with theHeadstage. -
ReferencePipeline.Head<T>is the starting point of the stream processing pipeline.
⚙️ ReferencePipeline.Head (Source Stage)
๐ Code Snippet:
It represents:
-
The source of elements (from
Spliterator). -
The starting node in the stream pipeline.
-
Whether the stream is parallel or not.
๐ What Happens Next?
After .stream() is called:
-
The stream pipeline is constructed (intermediate operations like
filter,mapwrap the pipeline). -
But no operation is executed yet!
Only when a terminal operation like .collect(), .forEach(), .reduce() is called does the pipeline trigger execution.
๐ Internal Stream Pipeline Architecture
Visual Representation:
๐งฉ Key Classes in Internals
| Class | Description |
|---|---|
Collection.stream() | Entry point from collections |
Iterable.spliterator() | Produces a Spliterator |
StreamSupport.stream() | Builds pipeline head |
ReferencePipeline.Head | First stage of the stream |
AbstractPipeline | Base for intermediate/terminal operations |
Spliterator | Source traverser/splitter |
Sink | Accepts and processes elements in pipeline stages |
✅ Summary
| Component | Description |
|---|---|
.stream() | Default method in Collection, delegates to StreamSupport.stream(...) |
spliterator() | Obtains an efficient traverser/splitter from the collection |
StreamSupport.stream() | Constructs pipeline head (ReferencePipeline.Head) |
ReferencePipeline | Represents lazy stages of the stream |
Terminal operation | Triggers actual traversal and processing |
๐ง Bonus: Parallel Streams
If you call .parallelStream() instead of .stream():
The true tells the pipeline to:
-
Enable parallel execution.
-
Use
ForkJoinPool.commonPool()for multi-threaded processing.
7) How many ways calls garbage collector
๐ 1. Using System.gc()
-
Suggests that the JVM perform garbage collection.
-
It calls
Runtime.getRuntime().gc()internally. -
Not guaranteed — JVM may ignore it.
๐ 2. Using Runtime.getRuntime().gc()
-
Similar to
System.gc(), but called explicitly through theRuntimeobject. -
Also just a request to the JVM.
๐ 3. Calling System.runFinalization()
-
Suggests that the JVM run finalizers on objects pending finalization.
-
Often used with
System.gc().
Example:
⚠️ Deprecated or discouraged in many cases because of unpredictable behavior.
๐ 4. Using finalize() Method (Deprecated)
-
JVM might call this before reclaiming the object.
-
Deprecated in Java 9+, and removed in Java 18+.
-
Should not be used in new code.
๐ 5. Nullifying References (Encouraging GC)
-
By removing strong references to an object, it becomes eligible for GC.
-
Actual collection depends on JVM.
๐ 6. Using PhantomReference, SoftReference, or WeakReference
These are classes in java.lang.ref package used to:
| Reference Type | Behavior |
|---|---|
SoftReference | Cleared at low memory |
WeakReference | Cleared at next GC cycle |
PhantomReference | Enqueued after object finalized |
-
Helps track or influence GC for caching and cleanup purposes.
๐ซ What You Cannot Do:
-
You cannot force GC to run at a specific time.
-
You cannot control the exact object removal timing.
-
JVM vendors have different GC implementations and optimizations.
๐ Summary Table
| Way | Method | Guaranteed? |
|---|---|---|
| 1 | System.gc() | ❌ No |
| 2 | Runtime.getRuntime().gc() | ❌ No |
| 3 | System.runFinalization() | ❌ No |
| 4 | finalize() | ❌ No (Deprecated) |
| 5 | Nullifying reference | ❌ No |
| 6 | Reference types (WeakReference, etc.) | ❌ No |
๐งช Bonus: JVM Options to Control GC Behavior
You can use JVM flags to influence GC algorithms and behavior:
ArrayList Operations in Java✅ Time Complexity of ArrayList in Java — Detailed Breakdown
ArrayList is part of the Java Collections Framework and is backed by a dynamic array. This means it offers fast access but can be slower for some insert/remove operations compared to linked structures.
๐ ArrayList Time Complexity Table
| Operation | Time Complexity | Explanation |
|---|---|---|
| add(E e) (at end) | O(1) (Amortized) |
Fast unless resizing is needed |
| add(int index, E element) | O(n) |
Worst-case: shifting elements to the right |
| get(int index) | O(1) |
Direct access via index |
| set(int index, E element) | O(1) |
Replaces element at index |
| remove(int index) | O(n) |
Elements are shifted left |
| remove(Object o) | O(n) |
May require scanning and shifting |
| contains(Object o) | O(n) |
Linear search |
| indexOf(Object o) | O(n) |
Linear search |
| clear() | O(n) |
Nulls all elements for GC |
| size() | O(1) |
Just returns internal size variable |
| iterator() / listIterator() | O(1) |
Lightweight creation |
| ensureCapacity(int minCap) | O(n) (copying) |
Resizes internal array |
| trimToSize() | O(n) (copying) |
Shrinks internal array |
๐ง Key Notes
✅ Amortized O(1) for add(E e)
-
Internally, if array capacity is full, it resizes (usually by 1.5x).
-
Resize involves copying all elements to a new array → O(n)
-
But since it doesn't happen every time, the average over time is O(1).
๐ remove(int index)
-
Removing shifts elements to the left.
-
Hence, O(n) in the worst case (if removing from beginning).
✅ Best Use Cases for ArrayList
| Scenario | Recommended? | Reason |
|---|---|---|
| Frequent random access | ✅ Yes | Fast get() and set() |
| Frequent additions at end | ✅ Yes | Amortized O(1) |
| Frequent insertion/removal at middle/start | ❌ No | Costly shifting (O(n)) |
๐ Internals Recap (How ArrayList Works)
-
Uses a backing array:
Object[] elementData. -
Tracks current number of elements:
int size. -
Resizes itself using:
18)Sample program for ArrayListSortSublist
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayListSortSublist {
public static void main(String[] args) {
// Create a mutable ArrayList from an immutable List.of(...)
List<Integer> list = new ArrayList<>(List.of(10, 6, 8, 4, 2, 5, 1, 3, 7, 9, 82, 42));
list.sort(Integer::compareTo); // or Collections.sort(list)
System.out.println("Sorted List: " + list);
// Print elements from index 4 to 9 (inclusive)
list.subList(4, 10).forEach(System.out::println);
List<Integer> lst = Arrays.asList(10, 6, 8, 4, 2, 5, 1, 3, 7, 9, 82, 42);
List<Integer> list2 = lst.stream().sorted().collect(Collectors.toList());
System.out.println("Sorted List: " + list2);
// Print elements from index 4 to 9 (inclusive)
list2.subList(4, 10).forEach(System.out::println);
}
}
19) Find common elements from 2 arrays
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CommonElementsin2Arrays {
public static void main(String[] args) {
Integer[] array1 = {1, 2, 3, 4, 5};
Integer[] array2 = {3, 4, 5, 6, 7};
List<Integer> common = Arrays.stream(array1)
.filter(num -> Arrays.asList(array2).contains(num))
.distinct()
.collect(Collectors.toList());
System.out.println("Common Elements: " + common);
}
}
20)Get the distinct characters with order and their count using stream()
import java.util.List;
import java.util.stream.Collectors;
public class DistinctCharsAndCount {
public static void main(String[] args) {
String str = "CCBBGHjdfhddf";
List<Character> distinctChars = str.chars() // Convert to IntStream of characters
.mapToObj(c -> (char) c) // Convert int to Character
.distinct() // Get distinct characters (preserves order)
.collect(Collectors.toList()); // Collect to list
long distinctCharsCount = str.chars() // Convert to IntStream of characters
.mapToObj(c -> (char) c) // Convert int to Character
.distinct() // Get distinct characters (preserves order)
.count();
System.out.println("Distinct characters in order: " + distinctChars); //[C, B, G, H, j, d, f, h] System.out.println("Distinct characters in order: " + distinctCharsCount); //8
}
}
๐ Explanation:
str.chars() → returns IntStream of Unicode values.
.mapToObj(c -> (char) c) → convert each Unicode int to Character.
.distinct() → filters out duplicates but retains the original order.
.collect(Collectors.toList()) → collects results into a list.21) How to get distinct characters and their count in a String?
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class EachCharactersAndTheirCounts {
public static void main(String[] args) {
String str= "programming";
Map<Character, Long> charCountMap = str.chars().mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println("Distinct Characters and Counts: " + charCountMap); //{p=1, a=1, r=2, g=2, i=1, m=2, n=1, o=1}
}
}
Example1 : Countcharacters using Function
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CountCharacters1 {
public static void main(String[] args) {
String str= "AAABBB";
Map<Character, Long> charCount = str.codePoints().mapToObj(Character::toString)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println("Each Characters and Counts: " + charCount);
}
}
23)Remove all duplicates and also exclude any numeric strings using stream
List<String> lst = Arrays.asList("abc","123","456","abc","ads");
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class RemoveDuplicExcludeInt {
public static void main(String[] args) {
List<String> lst = Arrays.asList("abc", "123", "456", "abc", "ads");
List<String> result = lst.stream()
.filter(s -> !s.matches("\\d+")) // Exclude numeric strings
.distinct() // Remove duplicates
.collect(Collectors.toList()); // Collect to list
System.out.println("Distinct elements: " + result);
}
}
27: Write a program to find employeename Groupby doj
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Employee1 {
private String name;
private LocalDate doj;
public Employee1(String name, LocalDate doj) {
this.name = name;
this.doj = doj;
}
public String getName() {
return name;
}
public LocalDate getDoj() {
return doj;
}
@Override
public String toString() {
return name;
}
}
public class GroupByDOJ {
public static void main(String[] args) {
// Sample employee data
List<Employee1> employees = Arrays.asList(
new Employee1("swamy", LocalDate.of(2021, 5, 15)),
new Employee1("Pranu", LocalDate.of(2020, 3, 20)),
new Employee1("Vaisu", LocalDate.of(2021, 5, 15)),
new Employee1("Srihan", LocalDate.of(2020, 3, 20)),
new Employee1("Raju", LocalDate.of(2019, 8, 10))
);
// Group employee names by DOJ
Map<LocalDate, List<String>> groupedByDOJ = employees.stream()
.collect(Collectors.groupingBy(
Employee1::getDoj, // Group by DOJ
Collectors.mapping(Employee1::getName, // Collect names
Collectors.toList()) // Collect into a list
));
// Print the grouped data
groupedByDOJ.forEach((doj, names) -> {
System.out.println("DOJ: " + doj + " -> Employees: " + names);
});
}
}
28: Write a program to remove the symbol [ from the string in Java
Srting str=This[Is[A[String
Using String.replace():
public class RemoveSymbol1 {
public static void main(String[] args) {
String str = "This[Is[A[String";
// Remove all occurrences of '['
String result = str.replace("[", "");
System.out.println(result);
}
}
Using String.replaceAll():
public class RemoveSymbol2 {
public static void main(String[] args) {
String str = "This[Is[A[String";
// Remove all occurrences of '[' using regex
String result = str.replaceAll("\\[", "");
System.out.println(result);
}
}
29: Write a program to add the symbol [ before every uppercase letter in the string using replaceAll()
String str="ThisIsAString"
public class AddSymbolBeforeCapsUsingString{
public static void main(String[] args) {
String str = "ThisIsAString";
// Add "[" before each uppercase letter
String result = str.replaceAll("([A-Z])", "[$1");
System.out.println(result);
}
}
30. What is the output for given code? String s = "test"; s.concat("java"); System.out.println(s);
Output: test
Because String is immutable in Java.
31. Can i extends FI1 with FT2?
@FunctionalInterface interface I2 { void show(); } @FunctionalInterface interface I1 extends I2 { void display(); // ❌ Now I1 has two abstract methods: show() + display() }
Ans: No
32. What is the output for given code?
class A {
void show() {
System.out.println("Inside A: show()");
}
}
class B extends Main {
void display() {
System.out.println("Inside B: display()");
}
}
class Main {
public static void main(String[] args) {
B a = new B();
}
}
Output: (no output)
35)How to swap two numbers without using a third variable?
public class swap {
public static void main(String[] args) {
int a = 10, b = 20;
a = a+b;
b =a-b;
a = a-b;
System.out.println(a);
System.out.println(b);
}
} 36)Separate vowels and consonants from given string
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SeparateVowCon {
public static void main(String[] args) {
String str = "Hi this is swamy, separating vowels and consonants";
List<Character> vowels = Arrays.asList('a','e','i','o','u');
Set<Character> charSet = str.chars().mapToObj(e->(char)e).collect(Collectors.toSet());
List<Character> listVowels = charSet.stream().filter(ch->vowels.contains(ch.toLowerCase(ch))).collect(Collectors.toList());
List<Character> listConsonants = charSet.stream().filter(ch->!vowels.contains(ch.toLowerCase(ch))).collect(Collectors.toList());
System.out.println("The listVowels"+listVowels);
System.out.println("The listConsonants"+listConsonants);
}
}
37)Java program to check if the given number is Prime
import java.util.Scanner;
public class PrimeNumberOrNot {
public static void main(String args[]) {
int i, m = 0, flag = 0;
Scanner sc = new Scanner(System.in);
System.out.println("Enter the integer:");
int number = sc.nextInt();
m = number / 2;
if (number == 0 || number == 1) {
System.out.println(number + " is not prime number");
} else {
for (i = 2; i <= m; i++) {
if (number % i == 0) {
System.out.println(number + " is not prime number");
flag = 1;
break;
}
}
if (flag == 0) {
System.out.println(number + " is prime number");
}
} // end of else
}
}
38a)Check given string is palindrome or not
public class StringPalindromeOrNot {
public static void main(String args[]) {
// Scanner sc=new Scanner(System.in);
// System.out.println("Please enter string: ");
// String str=sc.nextLine();
String str = "strts";
String revstr = "";
for (int i = str.length()- 1; i >= 0; i--)
revstr = revstr + str.charAt(i);
if (str.equals(revstr))
System.out.println(str + " is a palindrome.");
else
System.out.println(str + " is not a palindrome.");
}
}
38b)Check given number is palindrome or not
import java.util.Scanner;
public class NumberPalindromeOrNot {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter any number:");
int n = sc.nextInt();
sc.close();
if (isPalindrome(n)) {
System.out.println("Palindrome");
} else {
System.out.println("Not a palindrome");
}
}
private static boolean isPalindrome(int n) {
int original = n;
int reversed = reverseNumber(n);
return original == reversed;
}
private static int reverseNumber(int n) {
int reversed = 0;
while (n > 0) {
reversed = reversed * 10 + n % 10;
n /= 10;
}
return reversed;
}
}
39)Print number of largest polindrome in a string
import java.util.Scanner;
public class LargestPalindromeInString {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter a string:");
String input = sc.nextLine();
sc.close();
String largestPalindrome = findLargestPalindrome(input);
System.out.println("The largest palindrome in the string is: " + largestPalindrome);
}
// Method to find the largest palindrome
private static String findLargestPalindrome(String str) {
String largestPalindrome = "";
for (int i = 0; i < str.length(); i++) {
// Odd-length palindromes
String oddPalindrome = expandAroundCenter(str, i, i);
if (oddPalindrome.length() > largestPalindrome.length()) {
largestPalindrome = oddPalindrome;
}
// Even-length palindromes
String evenPalindrome = expandAroundCenter(str, i, i + 1);
if (evenPalindrome.length() > largestPalindrome.length()) {
largestPalindrome = evenPalindrome;
}
}
return largestPalindrome;
}
// Helper method to expand around center and check for palindrome
private static String expandAroundCenter(String str, int left, int right) {
while (left >= 0 && right < str.length() && str.charAt(left) == str.charAt(right)) {
left--;
right++;
}
return str.substring(left + 1, right);
}
}
40)Fibonacci Series
import java.util.Scanner;
public class NonRecursiveFibonacci {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number of Fibonacci numbers to generate:");
int n = sc.nextInt();
sc.close();
int firstFibonacci = 1;
int secondFibonacci = 1;
System.out.println(firstFibonacci);
System.out.println(secondFibonacci);
for (int i = 2; i < n; i++) {
int currentFibonacci = firstFibonacci + secondFibonacci;
System.out.println(currentFibonacci);
firstFibonacci = secondFibonacci;
secondFibonacci = currentFibonacci;
}
}
}
41) How to remove Whitespaces from String
//need to add below deppendency in pom.xml file
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
import org.apache.commons.lang3.StringUtils
public class RemoveWhitespaces {
public static void main(String[] args) {
// String input = " Hello World ! ";
// String result = StringUtils.deleteWhitespace(input);
// System.out.println("String without whitespaces: \"" + result + "\"");
String input = " Hello world ! ";
String result =StringUtils.deleteWhitespace(input);
System.out.println("String without whitespaces:"+result);
}
}
42) Sorting an array
import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class ArraySortUsingIntegerStringListStream{ public static void main(String[] args) { // Integer Array Integer[] arr = {5, 3, 9, 4, 6, 99}; System.out.println("Original Array: " + Arrays.toString(arr)); // Print sorted array using streams System.out.println("Ascending order:"); Arrays.stream(array).forEach(e -> System.out.print(e + " "));
// With Array.sort(): Arrays.sort(array);
// Ascending using Stream List<Integer> ascSorted = Arrays.stream(arr) .sorted() .collect(Collectors.toList()); System.out.println("Sorted (Ascending): " + ascSorted); // Descending using Stream List<Integer> descSorted = Arrays.stream(arr) .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println("Sorted (Descending): " + descSorted);
// Bubble sort remains as an algorithm example (not stream-based) Integer[] bubble = {5, 3, 9, 4, 6, 99}; for (int i = 0; i < bubble.length - 1; i++) { for (int j = 0; j < bubble.length - i - 1; j++) { if (bubble[j] > bubble[j + 1]) { int temp = bubble[j]; bubble[j] = bubble[j + 1]; bubble[j + 1] = temp; } } } System.out.println("Bubble Sorted: " + Arrays.toString(bubble)); // String Array String[] strArr = {"banana", "apple", "cherry", "date"}; System.out.println("Original String Array: " + Arrays.toString(strArr)); // Alphabetical sort List<String> sortedStrings = Arrays.stream(strArr) .sorted() .collect(Collectors.toList()); System.out.println("Sorted Strings (Alphabetical): " + sortedStrings); // Sort by length List<String> sortedByLength = Arrays.stream(strArr) .sorted(Comparator.comparingInt(String::length)) .collect(Collectors.toList()); System.out.println("Sorted by Length: " + sortedByLength); // List sorting with streams List<Integer> list = new ArrayList<>(Arrays.asList(5, 2, 8, 1, 3)); System.out.println("Original List: " + list); // Sort ascending using streams List<Integer> sortedListAsc = list.stream() .sorted() .collect(Collectors.toList()); System.out.println("List Sorted (Ascending): " + sortedListAsc); // Sort descending using streams List<Integer> sortedListDesc = list.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println("List Sorted (Descending): " + sortedListDesc); // Custom sort with stream (Even first, then odd) List<Integer> evenFirst = list.stream() .sorted((a, b) -> { if (a % 2 == 0 && b % 2 != 0) return -1; // a is even, b is odd → a comes first if (a % 2 != 0 && b % 2 == 0) return 1; // a is odd, b is even → b comes first return a - b; }) .collect(Collectors.toList()); System.out.println("List Sorted (Even First): " + evenFirst); } }
43) Find factorial of an integer?
public class Factorial {
public static void main(String[] args) {
int number = 5; // Input number
long factorial = 1;
for (int i = 1; i <= number; i++) {
factorial *= i;
}
System.out.println("Factorial of " + number + " is: " + factorial);
}
}
44) Difference between Java8 filter, groupby
The filter and groupBy operations in Java 8 serve different purposes in the Stream API.
1. Filter:
Filter is used to filter the elements from a stream based on a condition (predicate). and it returns only those elements that match the predicate.
Method Signature: Stream<T> filter(Predicate<? super T> predicate);
Use Case: Filter is used to retrieve a subset of elements from a collection or stream.
Example: import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class FilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Filter even numbers
List<Integer> evenNumbers = numbers.stream()
.filter(num -> num % 2 == 0)
.collect(Collectors.toList());
System.out.println("Even Numbers: " + evenNumbers);
}
}
2. groupBy:
groupBy is used to the group elements of a stream into a Map based on a classifier function.
and it returns a Map<K, List<T>> where K is the key generated by the classifier and List<T> is the list of items sharing the same key
Method: It is not directly part of the Stream API but is achieved using Collectors.groupingBy().
Use case: groupBy is used to categorize elements of a stream based on a specific property.
Example:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class GroupByExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "apricot", "blueberry", "cherry", "avocado");
// Group words by their first letter
Map<Character, List<String>> groupedByFirstLetter = words.stream()
.collect(Collectors.groupingBy(word -> word.charAt(0)));
System.out.println("Grouped Words: " + groupedByFirstLetter);
}
}
Key Differences:
| Feature | Filter | GroupBy |
|---|---|---|
| Purpose | Filters elements based on a condition. | Groups elements based on a classifier function. |
| Result | A Stream or collection with filtered elements. | A Map with grouped elements. |
| Return Type | Stream<T> | Map<K, List<T>> |
| Example Use | Get even numbers from a list. | Group words by their starting letter. |
45) Java map() and to toMap() Programs
1. map():
map() is used to transform elements in a stream into another form. It operates on each element and produces a new stream with transformed elements.
and it returns a Stream<R>, where R is the transformed type.
Use Case: map() is used to data transformation or mapping from one type to another (e.g., from String to Integer or from lowercase to uppercase).
Example:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MapExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Swamy", "Pranu", "Srihan");
// Convert names to uppercase using map()
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("Uppercase Names: " + upperCaseNames);
}
}
2. toMap():
toMap() is used to collect stream elements into a Map by applying key and value mapping functions.
and it returns a Map<K, U>, where K is the key and U is the value.
Use case: toMap() is used to create mappings (e.g., name to length, product to price).
Example:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ToMapExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Swamy", "Pranu", "Srihan");
// Create a map where key is the name and value is the length of the name
Map<String, Integer> nameLengthMap = names.stream()
.collect(Collectors.toMap(
name -> name, // Key mapper
name -> name.length() // Value mapper
));
System.out.println("Name Length Map: " + nameLengthMap);
}
}
Key Differences:
| Feature | map() | toMap() |
|---|---|---|
| Purpose | Transforms elements in a stream. | Collects elements into a Map. |
| Result | Produces a transformed Stream<R>. | Produces a Map<K, U> with custom key-value pairs. |
| Return Type | A Stream with transformed elements. | A Map with keys and values derived from the stream. |
| Use Case | Data transformation (e.g., convert to uppercase). | Create a mapping (e.g., name to length). |
CombinedExample: import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CombinedExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Swamy", "Pranu", "Srihan");
// Convert names to uppercase and collect them into a map
Map<String, Integer> upperCaseNameLengthMap = names.stream()
.map(String::toUpperCase) // Transform names to uppercase
.collect(Collectors.toMap(
name -> name, // Key mapper
name -> name.length() // Value mapper
));
System.out.println("Uppercase Name Length Map: " + upperCaseNameLengthMap);
}
}
46) Java 8 convert list into map
Converting a List to a Map in Java 8 involves using the Stream API and the Collectors.toMap() method.
The process can vary depending on the requirements, such as defining the keys and values, handling duplicate keys,
and customizing the map's behavior.
1. Basic Conversion
- Purpose: Convert a list to a map by defining how the keys and values are derived from the list elements.
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ListToMapBasicExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Swamy", "Pranu", "Srihan");
// Convert list to map where key is the name and value is the length of the name
Map<String, Integer> nameLengthMap = names.stream()
.collect(Collectors.toMap(
name -> name, // Key mapper
name -> name.length() // Value mapper
));
System.out.println("Name Length Map: " + nameLengthMap);
}
}
2. Handling Duplicate Keys
- If there are duplicate keys (e.g., two elements that map to the same key),
toMap()will throw anIllegalStateException. - To handle this, you can provide a merge function to resolve conflicts.
3. Custom Map Implementation
- By default,
toMap()creates aHashMap. You can specify a customMapimplementation, such asTreeMaporLinkedHashMap.
Example
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.TreeMap;
public class ListToMapCustomMap {
public static void main(String[] args) {
List<String> names = Arrays.asList("Swamy", "Pranu", "Srihan");
// Use a TreeMap for sorted keys
Map<String, Integer> nameLengthMap = names.stream()
.collect(Collectors.toMap(
name -> name, // Key mapper
name -> name.length(), // Value mapper
(existing, replacement) -> existing, // Merge function
TreeMap::new // Custom map supplier
));
System.out.println("Name Length Map: " + nameLengthMap);
}
}
4. Complex Object Conversion
- Convert a list of custom objects into a map by specifying a property for the key and another property (or the object itself) for the value.
Example
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Employee {
private int id;
private String name;
// Constructor
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
// Getters
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Employee{id=" + id + ", name='" + name + "'}";
}
}
public class ListToMapComplexExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee(1, "Swamy"),
new Employee(2, "Pranu"),
new Employee(3, "Srihan")
);
// Convert list to map where key is employee ID and value is the employee object
Map<Integer, Employee> employeeMap = employees.stream()
.collect(Collectors.toMap(
Employee::getId, // Key mapper
employee -> employee // Value mapper
));
System.out.println("Employee Map: " + employeeMap);
}
}
47) Functional interface in java 8
In Java, a functional interface is an interface that contains exactly one abstract method.
Functional interfaces can have any number of default and static methods, but only one abstract method.
They are primarily used as the target for lambda expressions and method references, enabling functional programming in Java.
Key Points About Functional Interfaces
- Marked with the
@FunctionalInterfaceannotation (optional but recommended to indicate intent). - Can contain
defaultandstaticmethods. - Used with lambda expressions for concise code.
The java.util.function package provides several built-in functional interfaces, such as Predicate, Consumer, Supplier, etc.
Example: Custom Functional Interface
interface MyFunctionalInterface { void displayMessage(String message); // Single abstract method }
public class FunctionalInterfaceExample { public static void main(String[] args) { // Implementing the functional interface using a lambda expression MyFunctionalInterface messagePrinter = (message) -> { System.out.println("Message: " + message); }; // Using the implemented method messagePrinter.displayMessage("Hello, Functional Interface!"); } }
Example: Using Built-in Functional Interface (Predicate)
The Predicate<T> functional interface takes a single input and returns a boolean result.
import java.util.function.Predicate; public class PredicateExample { public static void main(String[] args) { // Predicate to check if a number is greater than 10 Predicate<Integer> isGreaterThanTen = (num) -> num > 10; // Test the predicate System.out.println(isGreaterThanTen.test(15)); // Output: true System.out.println(isGreaterThanTen.test(8)); // Output: false } }
Runnable
public class LambdaRunnableExample {
public static void main(String[] args) {
// Without lambda: Anonymous inner class
Thread thread1 = new Thread(new Runnable() {
public void run() {
System.out.println("Thread 1 is running");
}
});
thread1.start();
// With lambda expression
Thread thread2 = new Thread(() -> System.out.println("Thread 2 is running"));
thread2.start();
}
}
Example 3: Using Lambda with a Built-in Functional Interface (Consumer)
The Consumer<T> functional interface takes an input and performs some action, without returning a result.
import java.util.function.Consumer;
public class LambdaConsumerExample {
public static void main(String[] args) {
Consumer<String> printMessage = message -> System.out.println("Message: " + message);
// Using the lambda expression
printMessage.accept("Lambda Expressions are powerful!");
}
}
Example 4: Using Lambda with Streams
import java.util.Arrays;
import java.util.List;
public class LambdaStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Using a lambda expression with forEach
numbers.forEach(number -> System.out.println(number * 2));
}
}
Benefits of Lambda Expressions
- Conciseness: Reduces boilerplate code.
- Readability: Simplifies the implementation of single-method interfaces.
- Improved Efficiency: Especially with collections and streams, lambda expressions make code easier to write and maintain.
49) Method References in Java 8
Method references are a shorthand notation of a lambda expression that executes a specific method.ClassName::staticMethodNameinstance::instanceMethodNameClassName::instanceMethodNameClassName::newExamples of Method References
Example 1: Static Method Reference:
Benefits of Method References
- Improves Readability: More concise than lambda expressions.
- Reusable Code: Directly we can pass references in existing methods.
- Integration with Functional Interfaces: Works seamlessly with Java's built-in functional interfaces.
Use Cases
- Simplifying lambda expressions when the method already exists.
- Processing collections using Streams API.
- Implementing functional interfaces in a clean and readable way.
1. HashMap
A HashMap is a collection that stores data in key-value pairs and provides
constant-time performance (O(1)) for basic operations like insert, delete, and lookup, assuming the hash function
disperses elements properly among the buckets.
Internal Structure of HashMap:
1.Hashing Mechanism:
a)HashMap uses a hash function to map keys to an index (bucket) in an internal array called a bucket array.
b)Each bucket stores a linked list (or tree in case of high collision) of Node objects containing the key, value, hash, and a reference to the next node.
2.Node Structure:
static class Node<K, V> { final int hash; final K key; V value; Node<K, V> next; }
3.Collision Handling:
Hash collisions are handled using chaining. Multiple keys with the same hash index
are stored in a linked list or binary tree.
4.Load Factor and Rehashing:
- Load factor (default: 0.75) determines when the HashMap should resize.
- When the number of elements exceeds
capacity * load factor, the HashMap doubles its size and rehashes all elements.
2. HashSet
A HashSet is a collection that uses a HashMap internally to store elements. It allows no duplicates
and provides constant-time performance (O(1)) for basic operations like add, remove, and contains.
Internal Structure of HashSet:
a)HashSet uses a HashMap to store elements.
b)Each element in the HashSet is stored as a key in the HashMap, with a constant dummy value (PRESENT).
3. ConcurrentHashMap
A ConcurrentHashMap is a thread-safe version of a HashMap that allows multiple threads
to access it concurrently without compromising performance.
Internal Structure of ConcurrentHashMap:
a)Segmentation:
i)Before Java 8: Used a segmented locking mechanism (separate locks for different buckets).
ii)From Java 8: Replaced segmentation with a bucket-level locking mechanism and improved performance
using a ConcurrentLinkedQueue or binary trees for collision handling.
b)Thread Safety:
i)Multiple threads can operate on different buckets concurrently.
ii)Locks are applied at the bucket level, not the entire map.
c)No Null Values:
ConcurrentHashMap does not allow null keys or null values to avoid ambiguity during concurrent access.
Example:
import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapExample { public static void main(String[] args) { ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); map.put("John", 50); map.put("Jane", 60); // Accessing elements concurrently System.out.println(map.get("John")); // Output: 50 } }
Comparison Table
| Feature | HashMap | HashSet | ConcurrentHashMap |
|---|---|---|---|
| Thread Safety | Not thread-safe | Not thread-safe | Thread-safe |
| Null Keys/Values | 1 null key, many null values | Allows null elements | Does not allow null keys or values |
| Performance | Fast (single thread) | Fast (single thread) | Good (multithreaded access) |
| Collision Handling | Linked List / Tree | Same as HashMap | Concurrent buckets |
51) Difference Between HashMap and ConcurrentHashMap
| Feature | HashMap | ConcurrentHashMap |
|---|---|---|
| Thread Safety | Not thread-safe. | Thread-safe, supports concurrent access. |
| Null Keys/Values | Allows one null key and multiple null values. | Does not allow null keys or null values. |
| Concurrency | Fails under concurrent modifications without external synchronization. | Optimized for multi-threaded environments using bucket-level locking. |
| Locking Mechanism | No locking; requires explicit synchronization for thread safety. | Uses bucket-level locking for better concurrency. |
| Performance | Fast for single-threaded applications. | Performs well under multi-threaded scenarios. |
| Iteration | May throw a ConcurrentModificationException during concurrent modifications. | No ConcurrentModificationException during iteration. |
| Read and Write Operations | Reads and writes are not atomic. | Reads are lock-free; writes lock buckets instead of the whole map. |
| Use Case | Suitable for single-threaded or low-concurrency applications. | Suitable for high-concurrency applications. |
Potential Issues with HashMap in Multi-threaded Scenarios:
- Data Corruption: Simultaneous writes may lead to inconsistent state.
- ConcurrentModificationException: Iteration during modification may fail.
Features of ConcurrentHashMap:
- Thread Safety: Operations like
put(),get(), andremove()are thread-safe. - Fine-Grained Locking: Only the bucket being modified is locked, allowing other threads to access different buckets.
- No Blocking for Reads: Read operations do not block even if writes are occurring on other buckets.
Key Points
- Use HashMap when thread-safety is not required, and the application is single-threaded or has minimal concurrency.
- Use ConcurrentHashMap in multi-threaded environments to avoid data corruption and improve performance with concurrent access.
Difference Between SynchronizedMap and ConcurrentHashMap
| Feature | SynchronizedMap (via Collections.synchronizedMap) | ConcurrentHashMap |
|---|---|---|
| Thread Safety | Thread-safe using a single lock on the entire map. | Thread-safe using bucket-level locking (lock striping). |
| Locking Mechanism | Entire map is locked during all operations, including reads and writes. | Locks individual buckets, allowing higher concurrency. |
| Concurrency Level | Only one thread can access the map at a time. | Multiple threads can operate on different buckets simultaneously. |
| Performance | Slower due to single lock for the entire map. | Faster due to fine-grained locking. |
| Iteration | Must explicitly synchronize during iteration to avoid ConcurrentModificationException. | No explicit synchronization required during iteration. |
| Null Keys/Values | Allows one null key and multiple null values. | Does not allow null keys or null values. |
| Use Case | Suitable for applications with low concurrency requirements. | Ideal for high-concurrency applications. |
Key Notes:
- Must explicitly synchronize the map during iteration.
- A single lock reduces throughput in multi-threaded environments.
Key Features:
- No need for explicit synchronization during iteration.
- Supports higher concurrency with bucket-level locking.
When to Use
SynchronizedMap:
- Use when the application is single-threaded or has low concurrency.
- Preferable when minimal synchronization overhead is acceptable.
ConcurrentHashMap:
- Use in high-concurrency applications to ensure better performance.
- Ideal when frequent reads and writes are required.
53) RemoveDuplicates from array
Explanation:
IntStream.of(array)→ Converts array to stream.-
.distinct()→ Filters out duplicate integers. -
.toArray()→ Converts the stream back to an array.
No comments:
Post a Comment