Backend Development 11 min read

Understanding Java Stream API: filter, map, flatMap, and Parallel Operations

This article explains how Java's Stream API enables efficient data processing through pipeline operations such as filter, map, flatMap, stream creation methods, conversion to collections, and parallel execution, providing code examples and practical usage guidelines.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Understanding Java Stream API: filter, map, flatMap, and Parallel Operations

The article introduces Java's Stream API as a powerful way to process data in a pipeline, improving efficiency and unifying functional programming across languages.

filter operation : Demonstrates filtering a list of maps to retain entries with a non‑null, non‑empty "ip" field, then processing each element.

list.stream().filter(smap -> null != smap.get("ip") && !"".equals(smap.get("ip"))).forEach(imp -> {
    listipzone.add(wry.findIP(imp.get("ip").toString()));
});

map operation : Shows how map transforms each element, changing the generic type of the resulting stream.

String[] dd = { "a", "b", "c" };
Stream
stream = Arrays.stream(dd);
stream.filter(str -> str.equals("a")).forEach(System.out::println);

Another example converts Integer values to String and extracts the name field from a custom Emp object.

public static void main(String[] args) {
  Integer[] dd = {1, 2, 3};
  Stream
stream = Arrays.stream(dd);
  stream.map(str -> Integer.toString(str)).forEach(str -> {
    System.out.println(str);
    System.out.println(str.getClass());
  });

  List
list = Arrays.asList(new Emp("a"), new Emp("b"), new Emp("c"));
  list.stream().map(emp -> emp.getName()).forEach(str -> {
    System.out.println(str);
  });
}

public class Emp {
  private String name;
  public Emp() { super(); }
  public Emp(String name) { super(); this.name = name; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
}

flatMap operation : Explains that flatMap receives a function returning a Stream and flattens nested streams into a single stream.

public static void main(String[] args) {
  String[] strs = {"aaa", "bbb", "ccc"};
  Arrays.stream(strs).map(str -> str.split(""))
        .forEach(System.out::println);
  Arrays.stream(strs).map(str -> str.split(""))
        .flatMap(Arrays::stream)
        .forEach(System.out::println);
  Arrays.stream(strs).map(str -> str.split(""))
        .flatMap(str -> Arrays.stream(str))
        .forEach(System.out::println);
}

Common ways to create streams include Stream.of , Arrays.stream , and collection .stream() methods, with examples of converting arrays and lists into streams.

Stream stream = Stream.of("a", "b", "c");
String[] strArray = new String[]{"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
List
list = Arrays.asList(strArray);
stream = list.stream();

Converting streams to other data structures shows how to collect results into arrays, lists, sets, stacks, strings, and maps using Collectors .

// Array
String[] strArray1 = stream.toArray(String[]::new);
// Collection
List
list1 = stream.collect(Collectors.toList());
List
list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set
set1 = stream.collect(Collectors.toSet());
Stack
stack1 = stream.collect(Collectors.toCollection(Stack::new));
// String
String str = stream.collect(Collectors.joining());
// Map grouping
Map
factoryMap = factoryConfigDOS.stream()
    .collect(Collectors.groupingBy(AgencyDailySalaryFactoryConfigDO::getFenceId,
        Collectors.mapping(AgencyDailySalaryFactoryConfigDO::getFactoryName, joining(","))));
// Map conversion with duplicate keys handling
Map
nameMap = incumbentExcelInfoList.stream()
    .collect(Collectors.toMap(info -> info.getIdCard(), info -> info.getName(), (k1, k2) -> k2));

It emphasizes that a Stream can be consumed only once, and that many APIs follow this pattern, which is valuable for big‑data processing and cross‑language compatibility.

The article lists intermediate operations (e.g., map , filter , distinct , sorted , peek , limit , skip , parallel ) and terminal operations (e.g., forEach , toArray , reduce , collect , min , max , count , anyMatch , findFirst ).

limit/skip example demonstrates extracting a sublist after limiting and skipping elements.

List
personList2 = persons.stream()
    .map(Person::getName)
    .limit(10)
    .skip(3)
    .collect(Collectors.toList());
System.out.println(personList2);

Finally, the article covers parallel streams: calling parallel() on an existing stream or using parallelStream() on a collection enables data parallelism across CPU cores.

int sumSize = Stream.of("Apple", "Banana", "Orange", "Pear")
    .parallel()
    .map(s -> s.length())
    .reduce(Integer::sum)
    .get();
assertEquals(sumSize, 21);
JavaBackend DevelopmentFunctional ProgrammingStream APIParallelism
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

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