The Java Stream API is a powerful addition to the Java programming language introduced in Java 8. It provides a functional-style approach to process data in collections or other sources, making it easier to perform operations on data in a declarative and concise manner. The Stream API allows you to efficiently process large amounts of data using functional programming constructs like map
, filter
, reduce
, and more.
Key characteristics of the Java Stream API:
filter
, map
, and sorted
, transform a stream into another stream, allowing for chaining of multiple operations.collect
, forEach
, and reduce
, produce a result or side effect, effectively closing the stream.parallel()
or parallelStream()
, enhancing performance for large datasets.
In Java, the Stream API provides the filter()
method, which is used to select elements from a stream that match a given condition or predicate. The filter()
operation creates a new stream containing only the elements that satisfy the specified criteria.
Here’s the syntax of the filter()
method:
Stream<T> filter(Predicate<? super T> predicate)
T
is the type of the elements in the stream.Predicate<? super T>
is a functional interface that represents the condition to be checked for each element in the stream.Now, let’s see an example of using the filter()
method to filter elements from a stream:
Example:
/** * The filter function filters based on a predicate(True/False). * * The items that pass the predicate are passed on to the next stream. * * Stream<T> filter(Predicate<? super T> predicate) */ static void doFilter() { System.out.println("doFilter..."); // filter on id that is greater than 3. List<User> filteredUsers = users.stream().filter(user -> { return user.getId() > 3; }).collect(Collectors.toList()); filteredUsers.forEach(user -> { System.out.println("User: " + user.toString()); }); System.out.println("doFilter done!"); }
Stream API provides the map() method, which is used to transform the elements of a stream from one type to another. It takes a Function as an argument, which is a functional interface representing a function that converts one value to another. The map() operation returns a new stream containing the transformed elements.
static void doMap() { System.out.println("doMap..."); List<Student> mappedStudents = users.stream().map(user -> { // @formatter:off // map user to student return Student.builder() .id(user.getId()) .firstName(user.getFirstName()) .lastName(user.getLastName()) .email(user.getEmail()) .phoneNumber(user.getPhoneNumber()) .build(); // @formatter:on }).collect(Collectors.toList()); mappedStudents.forEach(student -> { System.out.println("student: " + student.toString()); }); System.out.println("doMap done!"); }
Stream API provides the flatMap() method, which is used to flatten a stream of streams into a single stream. It takes a Function as an argument, which maps each element of the stream to another stream. The flatMap() operation then concatenates or flattens these inner streams into a single output stream. The flatMap() method is particularly useful when you have a stream of collections or arrays and want to operate on the elements of those collections individually rather than on the entire collection as a single element.
static void doFlatMap() { System.out.println("doFlatMap..."); List<List<Integer>> listOfLists = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9)); // @formatter:off // flatten a stream of streams into a single stream // flatmap function must return a stream List<Integer> flattenedList = listOfLists.stream() .flatMap(list -> list.stream()) .collect(Collectors.toList()); // @formatter:on flattenedList.forEach(number -> { System.out.println("number: " + number); }); System.out.println("doFlatMap done!"); }
The Stream API provides the sorted() method, which is used to sort the elements of a stream based on a specified comparator or the natural ordering of the elements. The sorted() method returns a new stream with the elements sorted according to the specified criteria.
//Stream<T> sorted() //Stream<T> sorted(Comparator<? super T> comparator) static void doSort() { System.out.println("doSort..."); List<User> sortedUsers = users.stream() // @formatter:off .sorted(new Comparator<User>() { @Override public int compare(User u1, User u2) { return u1.getFirstName().compareTo(u2.getFirstName()); } }) // .sorted(Comparator.comparingLong(User::getId)) // @formatter:on .collect(Collectors.toList()); sortedUsers.forEach(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doSort done!"); }
doCount()
static void doCount() { System.out.println("doCount..."); long count = users.stream().count(); System.out.println("count: " + count); System.out.println("doCount done!"); }
forEach()
static void doForEach() { System.out.println("doForEach..."); users.forEach(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doForEach done!"); }
findFirst()
static void doFindFirst() { System.out.println("doFindFirst..."); Optional<User> optUser = users.stream().findFirst(); optUser.ifPresent(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doFindFirst done!"); }
Stream API provides the anyMatch() method, which is used to check if any element in the stream satisfies a give condition or predicate. It returns a boolean value indicating whether at least one element in the stream matches the specified condition.
static void doAnyMatch() { System.out.println("doAnyMatch..."); boolean anyMatch = users.stream().anyMatch(user -> user.getFirstName().contains("mine")); System.out.println("anyMatch: " + anyMatch); System.out.println("doAnyMatch done!"); }
Stream API provides the allMatch() method, which is used to check if all elements in the stream satisfy a given condition or predicate. It returns a boolean value indicating whether every element in the stream matches the specified condition.
static void doAllMatch() { System.out.println("doAllMatch..."); boolean allMatch = users.stream().allMatch(user -> user.getFirstName().contains("a")); System.out.println("allMatch" + allMatch); System.out.println("doAllMatch done!"); }
Stream API provides the distinct() method, which is used to remove duplicate elements from a stream. It returns a new stream containing only the distinct elements based on their natural order (if available) or their implementation of equals() method.
static void doDistinct() { System.out.println("doDistinct..."); users.stream().distinct().forEach(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doDistinct done!"); }
doLimit()
static void doLimit() { System.out.println("doDistinct..."); users.stream().limit(3).forEach(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doDistinct done!"); }
doParallelStream()
static void doParallelStream() { System.out.println("doParallelStream..."); users.parallelStream().forEach(user -> { System.out.println("user: " + user.toString()); }); System.out.println("doParallelStream done!"); }
Stream API provides the max() method, which is used to find the maximum element of a stream based on a given comparator or the natural order of the elements. The max() method returns an Optional<T> that contains the maximum element, or an empty Optional if the stream is empty.
static void doMax() { System.out.println("doMax..."); Optional<User> maxUser = users.stream().max(new Comparator<User>() { @Override public int compare(User u1, User u2) { return u1.getFirstName().compareTo(u2.getFirstName()); } }); maxUser.ifPresent(user -> { System.out.println("Max User: " + user.toString()); }); System.out.println("doMax done!"); }
Stream API provides the min() method, which is used to find the minimum element of a stream based on a given comparator or the natural order of the elements. The min() method returns an Optional<T> that contains the minimum element, or an empty Optional if the stream is empty.
static void doMin() { System.out.println("doMin..."); Optional<User> maxUser = users.stream().min(new Comparator<User>() { @Override public int compare(User u1, User u2) { return u1.getFirstName().compareTo(u2.getFirstName()); } }); maxUser.ifPresent(user -> { System.out.println("Min User: " + user.toString()); }); System.out.println("doMin done!"); }