Java Stream API: LINQ-Style Collection Filtering & Extraction
This tutorial demonstrates Java Stream API for filtering and extracting collection data, covering stream creation from Lists, Sets, Maps, and arrays, key operations like filter, limit, skip, concat, distinct, and collecting results into List, Set, or Map with practical code examples.
Introduction
In .NET's C# language, collection filtering and extraction is done via LINQ, whose chained programming style is concise and readable. Java provides similar capabilities through the Stream API, though its functionality is not as rich as LINQ. Nevertheless, it eliminates the tedious steps of repeatedly looping through collections to filter and extract elements.
1. Generating a Stream
From Collection Types (List, Set)
For List and Set (Collection types), simply call the stream() method. Common List implementations: ArrayList, LinkedList. Common Set implementations: HashSet, TreeSet.
From Map Types
Map collections must first be converted to a Collection type to indirectly generate a Stream. Common Map classes: HashMap, TreeMap. Use keySet().stream() for keys, values().stream() for values, and entrySet().stream() for key-value entries.
From Arrays
Arrays use the static Arrays.stream() method.
From Ad-hoc Values
The static Stream.of(T... values) method creates a stream from a group of same-type values.
Code Example: Stream Creation
import java.util.*;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
// Collection types
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
// Map types
Map<String, Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
// Arrays
String[] strArray = {"jobs", "alpha", "monkey", "wolfer"};
Stream<String> strArrayStream = Arrays.stream(strArray);
// Stream.of
Stream<String> strArrayStream2 = Stream.of("winston", "reid", "celio");
Stream<Integer> intStream = Stream.of(11, 22, 33, 44);
}
}2. Common Stream Methods
The most frequently used methods are summarized below:
filter(Predicate) – filters elements in the stream.
limit(long maxSize) – retrieves the first N elements.
skip(long n) – skips the first N elements.
concat(Stream a, Stream b) – merges two streams into one.
distinct() – returns distinct elements (based on Object.equals).
forEach(Consumer) – iterates over each element.
count() – returns the number of elements.
Filter Example
Filter strings starting with "任" (Ren) and print them, then count them.
import java.util.ArrayList;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("任肥肥");
list.add("候胖胖");
list.add("任我行");
list.add("蔺赞赞");
list.add("任政富");
list.add("乔豆豆");
// Print strings starting with "任"
list.stream().filter(s -> s.startsWith("任")).forEach(System.out::println);
System.out.println("---------");
// Count strings starting with "任"
long count = list.stream().filter(s -> s.startsWith("任")).count();
System.out.println(count);
}
}Output:
任肥肥
任我行
任政富
---------
3Limit and Skip Example
import java.util.ArrayList;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("任肥肥");
list.add("候胖胖");
list.add("任我行");
list.add("蔺赞赞");
list.add("任政富");
list.add("乔豆豆");
// Print first 3
list.stream().limit(3).forEach(System.out::println);
System.out.println("---------");
// Skip first 3, print rest
list.stream().skip(3).forEach(System.out::println);
System.out.println("---------");
// Skip first 2, then limit to 2
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}Output:
任肥肥
候胖胖
任我行
---------
蔺赞赞
任政富
乔豆豆
---------
任我行
蔺赞赞Concat and Distinct Example
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("任肥肥");
list.add("候胖胖");
list.add("任我行");
list.add("蔺赞赞");
list.add("任政富");
list.add("乔豆豆");
// First 3 elements
Stream<String> s1 = list.stream().limit(3);
// Skip 1, take next 3
Stream<String> s2 = list.stream().skip(1).limit(3);
// Merge and print
Stream<String> s3 = Stream.concat(s1, s2);
s3.forEach(System.out::println);
System.out.println("---------");
// Note: once a terminal operation (forEach, count) executes, the stream is consumed.
// Re-create streams for further operations.
Stream.concat(list.stream().limit(3), list.stream().skip(1).limit(3))
.distinct()
.forEach(System.out::println);
}
}Output:
任肥肥
候胖胖
任我行
候胖胖
任我行
蔺赞赞
---------
任肥肥
候胖胖
任我行
蔺赞赞3. Collecting Stream Data into Collections
After terminal operations like forEach or count, the stream is closed. To retain results, use collect(Collector). The Collectors utility class provides:
toList() – collects elements into a List.
toSet() – collects elements into a Set.
toMap(Function keyMapper, Function valueMapper) – collects elements into a Map.
Collection Example
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String> personlist = new ArrayList<String>();
personlist.add("任肥肥,38岁");
personlist.add("候胖胖,40岁");
personlist.add("任我行,55岁");
personlist.add("蔺赞赞,34岁");
personlist.add("任政富,58岁");
personlist.add("乔豆豆,33岁");
// Filter strings starting with "任", collect to List
Stream<String> listStream1 = personlist.stream().filter(s -> s.startsWith("任"));
List<String> list = listStream1.collect(Collectors.toList());
for (String p : list) {
System.out.println(p);
}
System.out.println("---------");
// Filter, extract name (before comma), collect to Set
Stream<String> listStream2 = personlist.stream()
.filter(s -> s.startsWith("任"))
.map(s -> s.split(",")[0]);
Set<String> set = listStream2.collect(Collectors.toSet());
for (String name : set) {
System.out.println(name);
}
System.out.println("---------");
// Filter, extract name and age, collect to Map (name -> age)
Stream<String> listStream3 = personlist.stream().filter(s -> s.startsWith("任"));
Map<String, String> map = listStream3.collect(
Collectors.toMap(s -> s.split(",")[0], s -> s.split(",")[1]));
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key + " <----> " + map.get(key));
}
}
}Output:
任肥肥,38岁
任我行,55岁
任政富,58岁
---------
任我行
任肥肥
任政富
---------
任我行 <----> 55岁
任肥肥 <----> 38岁
任政富 <----> 58岁Many more Stream operations exist (e.g., max(), min()), all straightforward to use. Consult the JDK documentation when needed.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
