[Go to site: main page, start]

0% found this document useful (0 votes)
31 views18 pages

Java Stream API Coding Questions Guide

The document provides a series of Java Stream API coding questions, each with at least two approaches and explanations. It covers various operations such as filtering, mapping, reducing, and collecting data from lists and arrays. The examples illustrate different methods to achieve the same results, emphasizing performance tips and idiomatic usage.

Uploaded by

Puneet Prakash
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)
31 views18 pages

Java Stream API Coding Questions Guide

The document provides a series of Java Stream API coding questions, each with at least two approaches and explanations. It covers various operations such as filtering, mapping, reducing, and collecting data from lists and arrays. The examples illustrate different methods to achieve the same results, emphasizing performance tips and idiomatic usage.

Uploaded by

Puneet Prakash
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

Java Stream API — Basic Level (1–30) —

Coding Questions with Multiple


Approaches
Each problem includes at least two Stream-centric approaches, plus brief explanations and
notes.

1) Find all even numbers from a list


Approach 1:

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

List<Integer> list = [Link](1,2,3,4,5,6);


List<Integer> evens = [Link]()
.filter(n -> n % 2 == 0)
.collect([Link]());
[Link](evens);

Why it works: Use filter with a modulo predicate and collect to List.

Approach 2 (Alternative):

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

List<Integer> list = [Link](1,2,3,4,5,6);


List<Integer> evens = [Link]()
.collect([Link](n -> n % 2 == 0,
[Link]()));
[Link](evens);

Why it works: Using [Link] (Java 9+) pushes the predicate into the downstream
collector.

Notes: Performance tip: prefer primitive streams when doing heavy numeric work.

2) Convert a list of strings to uppercase


Approach 1:
import [Link].*;
import [Link].*;

List<String> names = [Link]("java","stream","api");


List<String> upper = [Link]()
.map(String::toUpperCase)
.collect([Link]());
[Link](upper);

Why it works: map with method reference for clarity.

Approach 2 (Alternative):

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

List<String> names = [Link]("java","stream","api");


List<String> upper = [Link]()
.collect([Link](String::toUpperCase,
[Link]()));
[Link](upper);

Why it works: [Link] (Java 9+) performs the transform in the collector.

3) Find the sum of all numbers in a list


Approach 1:

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

List<Integer> nums = [Link](1,2,3,4);


int sum = [Link]().mapToInt(Integer::intValue).sum();
[Link](sum);

Why it works: mapToInt creates IntStream enabling sum().

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,3,4);


int sum = [Link]().reduce(0, Integer::sum);
[Link](sum);
Why it works: reduce with identity & accumulator keeps boxing but is concise.

Notes: Prefer primitive streams (mapToInt) to avoid boxing.

4) Find the maximum number in a list


Approach 1:

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

List<Integer> nums = [Link](3,7,2,9,5);


int max =
[Link]().mapToInt(Integer::intValue).max().orElseThrow();
[Link](max);

Why it works: Use [Link] + orElseThrow for empty handling.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](3,7,2,9,5);


int max = [Link]().reduce(Integer::max).orElseThrow();
[Link](max);

Why it works: reduce with Integer::max avoids converting to primitive stream.

5) Find the minimum number in a list


Approach 1:

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

List<Integer> nums = [Link](3,7,2,9,5);


int min =
[Link]().mapToInt(Integer::intValue).min().orElse([Link]
N_VALUE);
[Link](min);

Why it works: [Link] with fallback.

Approach 2 (Alternative):
import [Link].*;
import [Link].*;

List<Integer> nums = [Link](3,7,2,9,5);


int min =
[Link]().min([Link]()).orElseThrow();
[Link](min);

Why it works: [Link] with Comparator.

6) Count the number of strings starting with a specific letter


Approach 1:

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

List<String> words =
[Link]("apple","banana","apricot","cherry");
long count = [Link]()
.filter(s -> [Link]("a"))
.count();
[Link](count);

Why it works: Filter then count.

Approach 2 (Alternative):

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

List<String> words =
[Link]("apple","banana","apricot","cherry");
long count = [Link]()
.collect([Link](s -> [Link]("a"),
[Link]()));
[Link](count);

Why it works: Use [Link] + counting.

7) Remove duplicate elements from a list


Approach 1:

import [Link].*;
import [Link].*;
List<Integer> nums = [Link](1,2,2,3,3,3,4);
List<Integer> distinct =
[Link]().distinct().collect([Link]());
[Link](distinct);

Why it works: distinct uses equals/hashCode.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,2,3,3,3,4);


List<Integer> distinct = new ArrayList<>(new
LinkedHashSet<>(nums));
[Link](distinct);

Why it works: Alternative not strictly streams: LinkedHashSet preserves order then back to
list.

8) Sort a list in ascending order


Approach 1:

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

List<Integer> nums = [Link](4,1,3,2);


List<Integer> sorted =
[Link]().sorted().collect([Link]());
[Link](sorted);

Why it works: sorted() natural order.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](4,1,3,2);


List<Integer> sorted =
[Link]().sorted([Link]()).collect(Collector
[Link]());
[Link](sorted);
Why it works: Explicit comparator for readability or generic code.

9) Sort a list in descending order


Approach 1:

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

List<Integer> nums = [Link](4,1,3,2);


List<Integer> desc =
[Link]().sorted([Link]()).collect(Collector
[Link]());
[Link](desc);

Why it works: Reverse natural order.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](4,1,3,2);


List<Integer> desc = [Link]()
.sorted((a,b) -> [Link](b,a))
.collect([Link]());
[Link](desc);

Why it works: Custom comparator, equivalent.

10) Find the first element of a list


Approach 1:

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

List<String> list = [Link]("a","b","c");


String first = [Link]().findFirst().orElse(null);
[Link](first);

Why it works: findFirst returns Optional; choose default.

Approach 2 (Alternative):
import [Link].*;
import [Link].*;

List<String> list = [Link]("a","b","c");


String first =
[Link]().limit(1).collect([Link](Collectors
.toList(), l -> [Link]()? null : [Link](0)));
[Link](first);

Why it works: Limit + collectingAndThen shows collector post-processing.

11) Check if any element in the list matches a condition


Approach 1:

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

List<Integer> nums = [Link](1,3,5,8);


boolean hasEven = [Link]().anyMatch(n -> n % 2 == 0);
[Link](hasEven);

Why it works: anyMatch short-circuits on first match.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,3,5,8);


boolean hasEven = [Link]().filter(n -> n % 2 ==
0).findAny().isPresent();
[Link](hasEven);

Why it works: Filter + findAny equivalent but less efficient.

12) Check if all elements match a condition


Approach 1:

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

List<Integer> nums = [Link](2,4,6);


boolean allEven = [Link]().allMatch(n -> n % 2 == 0);
[Link](allEven);
Why it works: allMatch checks all with short-circuiting.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](2,4,6);


boolean allEven = ![Link]().anyMatch(n -> n % 2 != 0);
[Link](allEven);

Why it works: Logical negation of anyMatch.

13) Check if no elements match a condition


Approach 1:

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

List<String> words = [Link]("cat","dog");


boolean noneLongerThan5 = [Link]().noneMatch(s ->
[Link]() > 5);
[Link](noneLongerThan5);

Why it works: noneMatch is the negation of anyMatch.

Approach 2 (Alternative):

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

List<String> words = [Link]("cat","dog");


boolean noneLongerThan5 = [Link]().allMatch(s ->
[Link]() <= 5);
[Link](noneLongerThan5);

Why it works: Equivalent using allMatch.

14) Filter null values from a list


Approach 1:

import [Link].*;
import [Link].*;
List<String> list = [Link]("a", null, "b", null, "c");
List<String> nonNull =
[Link]().filter(Objects::nonNull).collect([Link]());
[Link](nonNull);

Why it works: Objects::nonNull is idiomatic.

Approach 2 (Alternative):

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

List<String> list = [Link]("a", null, "b", null, "c");


List<String> nonNull = [Link]().flatMap(s -> s == null ?
[Link]() : [Link](s)).collect([Link]());
[Link](nonNull);

Why it works: flatMap to drop nulls.

15) Convert a list of integers to their square values


Approach 1:

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

List<Integer> nums = [Link](1,2,3,4);


List<Integer> squares = [Link]().map(n ->
n*n).collect([Link]());
[Link](squares);

Why it works: map applies a pure function.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,3,4);


int[] squares = [Link]().mapToInt(n -> n*n).toArray();
[Link]([Link](squares));

Why it works: Primitive stream to array.


16) Collect stream results into a Set instead of a List
Approach 1:

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

List<Integer> nums = [Link](1,2,2,3);


Set<Integer> set = [Link]().collect([Link]());
[Link](set);

Why it works: [Link] uses HashSet by default (no order).

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,2,3);


Set<Integer> set =
[Link]().collect([Link](LinkedHashSet::new));
[Link](set);

Why it works: Use toCollection to choose a Set implementation and preserve insertion
order.

17) Join a list of strings into a single comma-separated string


Approach 1:

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

List<String> parts = [Link]("a","b","c");


String csv = [Link]().collect([Link](","));
[Link](csv);

Why it works: [Link] with delimiter.

Approach 2 (Alternative):

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

List<String> parts = [Link]("a","b","c");


String csv = [Link](",", parts);
[Link](csv);

Why it works: Alternative using [Link] (not a stream but idiomatic).

18) Find the average of a list of numbers


Approach 1:

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

List<Integer> nums = [Link](1,2,3,4);


double avg =
[Link]().mapToInt(Integer::intValue).average().orElse(0.0);
[Link](avg);

Why it works: [Link] returns OptionalDouble.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,3,4);


double avg =
[Link]().collect([Link](Integer::intValue));
[Link](avg);

Why it works: Use averaging collector for readability.

19) Convert a list of objects to a list of one of their fields


Approach 1:

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

record User(int id, String name) {}


List<User> users = [Link](new User(1,"A"), new User(2,"B"));
List<String> names =
[Link]().map(User::name).collect([Link]());
[Link](names);

Why it works: Method reference to accessor.


Approach 2 (Alternative):

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

class User { int id; String name; User(int i,String n){id=i;name=n;}


String getName(){return name;} }
List<User> users = [Link](new User(1,"A"), new User(2,"B"));
Set<String> names =
[Link]().collect([Link](User::getName,
[Link]()));
[Link](names);

Why it works: [Link] to a Set.

20) Skip the first N elements in a stream


Approach 1:

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

List<Integer> nums = [Link](10,20,30,40,50);


List<Integer> after2 =
[Link]().skip(2).collect([Link]());
[Link](after2);

Why it works: skip(n) discards the first n elements.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](10,20,30,40,50);


List<Integer> after2 = [Link](0, [Link]())
.filter(i -> i >= 2)
.mapToObj(nums::get)
.collect([Link]());
[Link](after2);

Why it works: Index-based filter as an alternative.

21) Limit a stream to the first N elements


Approach 1:
import [Link].*;
import [Link].*;

List<Integer> nums = [Link](10,20,30,40,50);


List<Integer> first3 =
[Link]().limit(3).collect([Link]());
[Link](first3);

Why it works: limit(n) short-circuits after n elements.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](10,20,30,40,50);


List<Integer> first3 = [Link](0, [Link](3, [Link]()))
.mapToObj(nums::get)
.collect([Link]());
[Link](first3);

Why it works: Index slicing alternative.

22) Convert a primitive array to a stream and process it


Approach 1:

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

int[] arr = {1,2,3,4};


int sum = [Link](arr).filter(n -> n%2==0).sum();
[Link](sum);

Why it works: [Link] for primitive arrays yields IntStream.

Approach 2 (Alternative):

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

int[] arr = {1,2,3,4};


long count = [Link](arr).filter(n -> n%2==0).count();
[Link](count);
Why it works: [Link] is equivalent for int[].

23) Use mapToInt() to sum a list of numbers


Approach 1:

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

List<Integer> nums = [Link](5,6,7);


int sum = [Link]().mapToInt(Integer::intValue).sum();
[Link](sum);

Why it works: Straightforward primitive stream sum.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](5,6,7);


int sum =
[Link]().collect([Link](Integer::intValue));
[Link](sum);

Why it works: Use summingInt collector.

24) Convert a list of lists into a single list (flatMap)


Approach 1:

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

List<List<Integer>> lol = [Link]([Link](1,2),


[Link](3,4));
List<Integer> flat =
[Link]().flatMap(List::stream).collect([Link]());
[Link](flat);

Why it works: flatMap flattens nested streams.

Approach 2 (Alternative):

import [Link].*;
import [Link].*;
List<List<Integer>> lol = [Link]([Link](1,2),
[Link](3,4));
Set<Integer> flatDistinct = [Link]()
.flatMap(Collection::stream)

.collect([Link](LinkedHashSet::new));
[Link](flatDistinct);

Why it works: Flatten + collect with a specific collection type.

25) Filter a list of strings based on length


Approach 1:

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

List<String> words = [Link]("a","abcd","xyz","hello");


List<String> longOnes = [Link]().filter(s -> [Link]() >=
3).collect([Link]());
[Link](longOnes);

Why it works: Basic filter on property.

Approach 2 (Alternative):

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

List<String> words = [Link]("a","abcd","xyz","hello");


List<String> longOnes = [Link]()
.collect([Link](s -> [Link]() >= 3,
[Link]()));
[Link](longOnes);

Why it works: [Link] variant.

26) Generate a list of random numbers using streams


Approach 1:

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

List<Double> rnd =
[Link](Math::random).limit(5).collect([Link]());
[Link](rnd);

Why it works: [Link] supplier + limit.

Approach 2 (Alternative):

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

Random r = new Random();


List<Integer> ints = [Link](5, 1,
101).boxed().collect([Link]());
[Link](ints);

Why it works: Use [Link] to produce bounded IntStream.

27) Find distinct characters from a string using streams


Approach 1:

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

String s = "banana";
List<Character> chars = [Link]().mapToObj(c ->
(char)c).distinct().collect([Link]());
[Link](chars);

Why it works: chars() -> IntStream, then box to Character.

Approach 2 (Alternative):

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

String s = "banana";
String unique = [Link]()
.distinct()
.collect(StringBuilder::new,
StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
[Link](unique);

Why it works: Collect distinct code points back into a String.


28) Partition a list into even and odd numbers
Approach 1:

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

List<Integer> nums = [Link](1,2,3,4,5,6);


Map<Boolean, List<Integer>> parts = [Link]()
.collect([Link](n -> n % 2 ==
0));
[Link](parts);

Why it works: partitioningBy yields two buckets (true/false).

Approach 2 (Alternative):

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

List<Integer> nums = [Link](1,2,3,4,5,6);


Map<Boolean, Set<Integer>> parts = [Link]()
.collect([Link](n -> n % 2 == 0,
[Link](LinkedHashSet::new)));
[Link](parts);

Why it works: Downstream collector to control collection type.

29) Remove empty strings from a list


Approach 1:

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

List<String> words = [Link]("a","","b"," ","c");


List<String> nonEmpty = [Link]().filter(s ->
![Link]()).collect([Link]());
[Link](nonEmpty);

Why it works: Filter by String::isEmpty negation.

Approach 2 (Alternative):

import [Link].*;
import [Link].*;
List<String> words = [Link]("a","","b"," ","c");
List<String> trimmedNonBlank = [Link]()
.map(String::trim)
.filter(s -> ![Link]())
.collect([Link]());
[Link](trimmedNonBlank);

Why it works: Trim first, then remove blanks (Java 11 String::isBlank).

30) Get the second-largest number in a list


Approach 1:

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

List<Integer> nums = [Link](5,9,1,9,3,7);


int second = [Link]()
.distinct()
.sorted([Link]())
.skip(1)
.findFirst()
.orElseThrow();
[Link](second);

Why it works: Distinct to avoid duplicates, reverse sort, skip first.

Approach 2 (Alternative):

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

List<Integer> nums = [Link](5,9,1,9,3,7);


int second = [Link]()
.collect([Link](
[Link](() -> new
TreeSet<>([Link]())),
set -> [Link]().skip(1).findFirst().orElseThrow()
));
[Link](second);

Why it works: Collect to a reversed TreeSet (unique + ordered), then take the second.

Common questions

Powered by AI

The Java Stream API offers two approaches to removing duplicates: The first approach utilizes the `distinct()` method on a stream, which relies on `equals()` and `hashCode()` for removing duplicates, and can be quite performant for handling large initial datasets . The second approach involves leveraging a `LinkedHashSet` to maintain the insertion order, where the elements of the list are first converted into a `LinkedHashSet` and then back to a list. This second approach is not strictly a stream operation but can be used for ordered results . The performance of the `distinct()` approach may be more efficient with large datasets because it avoids the overhead of creating additional data structures, whereas using `LinkedHashSet` provides a more readable option with an ordered output.

Java Streams can handle null values in a list using two main approaches. The first approach uses `filter(Objects::nonNull)` to filter out nulls in a straightforward and idiomatic way . Another alternative is to use `flatMap` combined with a conditional `Stream.empty()` for nulls, which achieves the same effect but may be less readable to those not familiar with `flatMap()` . When choosing between these methods, consider readability and maintainability: `filter(Objects::nonNull)` is clearer and more concise, while the `flatMap` method allows for more complex transformations if needed.

The Stream API supports aggregation operations such as finding maximum values using `mapToInt().max()`, which converts elements to an `IntStream` using a function, enabling efficient aggregation by avoiding boxing . Alternatively, `reduce(Integer::max)` can achieve the same result by applying the `max` operation through a Stream interface without converting to an `IntStream`, thereby working with boxed integers and making it potentially less efficient for large datasets . While both methods return equivalent results, `mapToInt().max()` generally provides better performance due to lesser memory overhead from avoiding unnecessary boxing operations. However, `reduce()` offers more flexibility in modifying the operation logic beyond simply finding the maximum.

Practical applications of partitioning with Java Streams include separating data into two distinct groups based on a binary predicate, like splitting numbers into odd and even categories. `Collectors.partitioningBy()` offers a straightforward method to achieve this by generating a `Map<Boolean, List<T>>` that categorizes data entries . However, when using it, consider the potential memory footprint as the operation involves creating two distinct lists in memory, which could be substantial with large datasets. Additionally, use appropriate downstream collectors within `partitioningBy` to control the resulting collection type, especially if set behavior or maintaining insertion order is desired .

Using `Collectors` for transformation operations such as mapping or filtering in Java Streams offers certain benefits, including increased readability and potential integration with complex collection operations. For example, `Collectors.mapping()` directly integrates a mapping function with downstream collection logic, which can simplify code and enhance its declarative style . Similarly, `Collectors.filtering()` allows embedding filter criteria within the collection process itself, which may simplify pipelining operations depending on the application's needs . However, these operations require Java 9 or later, which could limit compatibility with older Java environments, and they might obfuscate performance considerations by abstracting details away from developers familiar with traditional Stream pipelines.

In Java Streams, filter-based approaches for summing numbers typically involve using `mapToInt()` to convert elements to an `IntStream` and then applying the `sum()` operation, which avoids boxing and works directly on primitive types. This approach is efficient due to the use of primitive streams . The collector-based alternative employs `reduce()` with an identity and the `Integer::sum` accumulator, which, while concise, requires boxing of integers . Both methods ultimately yield the same numerical result, but the filter-based method with `mapToInt()` may perform better due to the reduced overhead from avoiding boxing.

The Java Stream API's use of `flatMap()` to manage nested lists offers improved readability and reduces boilerplate code compared to traditional nested loops. `flatMap()` directly transforms each nested list element into a single continuous stream of elements, eliminating the need for multiple nested iterations typical in loops . This reduces code complexity and enhances clarity by providing a declarative approach where developers can focus on the 'what' rather than the 'how' of element processing. Functionally, `flatMap()` also allows seamless integration with other stream operations such as filtering, mapping, and collection, providing a modular pipeline that processes data in a functional style.

You might also like