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.