BreadcrumbHomeResourcesBlog Using Java 8 Stream Map and Java 8 Stream Filter June 17, 2013 Using Java 8 Stream Map and Java 8 Stream FilterJava Application DevelopmentJava UpdatesJava 8 introduced Lambdas and a number of bulk data operations for collections, including Java stream map, Java stream filter, and Java forEach. In this blog post we will take a dive into bulk data operations for Java collections, including a look at how to use stream map, stream filter, foreach and collect() operators.Table of ContentsBulk Operations: map, foreach, filters for Java 8 streamsJava 8 Stream API: map, filter, foreachJava 8 Stream Filter ExampleJava 8 Stream Map ExampleUsing Collect() to Convert Java Stream to ListGet More Development HelpTable of Contents1 - Bulk Operations: map, foreach, filters for Java 8 streams2 - Java 8 Stream API: map, filter, foreach3 - Java 8 Stream Filter Example4 - Java 8 Stream Map Example5 - Using Collect() to Convert Java Stream to List6 - Get More Development HelpJava 8 Usage and TrendsHow many developers are using Java 8 in 2022? Download the 2022 Java Developer Productivity Report to find out JDK trends and more.GET REPORTBack to topBulk Operations: map, foreach, filters for Java 8 streamsAs the original specification for JEP 107: Bulk Data Operations for Collections says, the purpose of bulk operations is to "add functionality to the Java Collections Framework for bulk operations upon data. […] Operations upon data are generally expressed as lambda functions". This quote reveals the actual goal of Java stream lambda and shifts the focus of Java 8 release for me: the most important feature is actually the new way of using Java collections - expressing operations that could be executed concurrently and lambdas are just the better tool for expressing the operations. Let's look at a few Java 8 collections examples.Internal vs External Iteration in Java Collections: for vs. foreachHistorically, Java collections were not capable to express internal iteration as the only way to describe iteration flow was the for (or while) loop. For a Java 8 collections stream describing the internal iteration we would use libraries, such as LambdaJ: List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John")); forEach(persons).setLastName("Doe");In the example above, we do not actually say how the last name should be set to each individual person - maybe the operation could be performed concurrently. Now we could express the operations in a similar way with Java 8: persons.forEach(p -> p.setLastName("Doe"))The Java 8 forEach operation is available on any list object and it accepts a function to work on every element of the list. The internal iteration isn't that much related to bulk operations over collections. This is rather a minor feature that gives us an idea of what will be the effect of syntax changes. What is actually interesting in regards to bulk data operations is the new Stream API. Further in this post we'll show how to filter a list or set a Java 8 stream filter and how to convert a stream to a regular set or a list.Back to topJava 8 Stream API: map, filter, foreachThe new java.util.stream package has been added to JDK which allows us to perform filter/map/reduce-like operations with the Java 8 collections stream. The Stream API would allow us to declare either sequential or parallel operations over the stream of data: List persons = … // sequential version Stream stream = persons.stream(); //parallel version Stream parallelStream = persons.parallelStream(); The java.util.stream. Stream interface serves as a gateway to the bulk data operations. After the reference to a stream instance is acquired, we can perform the interesting tasks with the collections.Back to topJava 8 Stream Filter ExampleFiltering a stream of data is the first natural operation that we would need. Stream interface exposes a Java collection filter method that takes in a Predicate SAM that allows us to use lambda expression to define the filtering criteria: List persons = … Stream personsOver18 = persons.stream().filter(p -> p.getAge() > 18);Now the thing is that often you want to filter a List just like in the example above. Then you can easily convert the list to a stream, filter and collect the results back to a list if necessary.Back to topJava 8 Stream Map ExampleAssume we now have a filtered data that we can use for the real operations, say transforming the objects. The map operations allows us to apply a function (http://javadocs.techempower.com/jdk18/api/java/util/function/Function.html ), that takes in a parameter of one type, and returns something else. First, let's see how it would have been described in the good 'ol way, using an anonymous inner class: Stream students = persons.stream() .filter(p -> p.getAge() > 18) .map(new Function<Person, Student>() { @Override public Student apply(Person person) { return new Student(person); } });Now, converting this example into a lambda syntax we get the following: Stream students = persons.stream() .filter(p -> p.getAge() > 18) .map(person -> new Student(person));And since the lambda that is passed to the map method just consumes the parameter without doing anything else with it, then we can transform it further to a method reference: Stream students = persons.stream() .filter(p -> p.getAge() > 18) .map(Student::new); Back to topUsing Collect() to Convert Java Stream to ListWhile stream abstraction is continuous by its nature, we can describe the operations on streams but to acquire the final results we have to collect the data somehow. The Stream API provides a number of "terminal" operations. The collect() method is one of those terminals that allows us to collect the results of the operations: List students = persons.stream() .filter(p -> p.getAge() > 18) .map(Student::new) .collect(new Collector<Student, List>() { … }); Using the Collectors Utility ClassFortunately, in most cases you wouldn't need to implement the Collector interfaces yourself. Instead, there's a Collectors utility class for convenience: List students = persons.stream() .filter(p -> p.getAge() > 18) .map(Student::new) .collect(Collectors.toList());Or in case if we would like to use a specific collection implementation for collecting the results: List students = persons.stream() .filter(p -> p.getAge() > 18) .map(Student::new) .collect(Collectors.toCollection(ArrayList::new));In the example above you see how we collect Java 8 stream to a list. In the same way you can easily convert your stream to a set or a map using something like: Collectors.toCollection(HashSet::new)).Parallel and Sequential Streams ExampleOne interesting feature of the new Stream API is that it doesn't require to operations to be either parallel or sequential from beginning till the end. It is possible to start consuming the data concurrently, then switch to sequential processing and back at any point in the flow: List students = persons.stream() .parallel() .filter(p -> p.getAge() > 18) // filtering will be performed concurrently .sequential() .map(Student::new) .collect(Collectors.toCollection(ArrayList::new));The hidden agenda here is that the concurrent part of data processing flow will manage itself automatically, (hopefully) without requiring us to deal with the concurrency issues.Back to topGet More Development HelpIs your team of Java developers impacted by the developer shortage? Our on-demand webinar covers how the developer shortage is impacting Java teams, and strategies organizations can employ to improve developer retention and output while attracting new talent. Click below to stream now. You can also save time by skipping rebuilds and redeploys using JRebel. Give it a try free for 14 days and see how it impacts your development.▶ Solve Java developer shortage or boost developer productivityBack to top