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.

Java Captain
Java Captain
Java Captain
Java Stream API: LINQ-Style Collection Filtering & Extraction

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:

任肥肥
任我行
任政富
---------
3

Limit 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaData ProcessingFunctional ProgrammingCollectionsStream APIFilteringJava 8LINQ
Java Captain
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.