How do I use filter() method of Optional object?

The java.util.Optional class in Java provides a filter method. It’s used to apply a condition on the value held by this Optional.

Here is an example of how to use Optional‘s filter method:

package org.kodejava.util;

import java.util.Optional;

public class OptionalFilter {
    public static void main(String[] args) {

        // Creating Optional object and assigning a value
        Optional<String> myOptional = Optional.of("Hello");

        // Applying filter method on Optional
        Optional<String> result = myOptional.filter(value -> value.length() > 5);

        // Print the result
        // This will not print anything because the length of "Hello" 
        // is not greater than 5.
        result.ifPresent(System.out::println);
    }
}

In this example, the filter method is used to apply a condition on the value held by this myOptional object. The condition is that the length of the value should be greater than 5. If the value satisfies the condition, it is returned. Otherwise, an empty Optional object is returned.

The ifPresent method is used to print the value held by this Optional, if it is non-empty. This particular use of filter will not print anything because the string “Hello” length is not greater than 5.

You can use isEmpty method to check whether Optional is empty.

if (result.isEmpty()) {
   System.out.println("The Optional is empty");
}

In this case, it would print “The Optional is empty”.

How do I use map, filter, reduce in Java Stream API?

The map(), filter(), and reduce() methods are key operations used in Java Stream API which is used for processing collection objects in a functional programming manner.

Java Streams provide many powerful methods to perform common operations like map, filter, reduce, etc. These operations can transform and manipulate data in many ways.

  • map: The map() function is used to transform one type of Stream to another. It applies a function to each element of the Stream and then returns the function’s output as a new Stream. The number of input and output elements is the same, but the type or value of the elements may change.

Here’s an example:

package org.kodejava.basic;

import java.util.Arrays;
import java.util.List;

public class MapToUpperCase {
    public static void main(String[] args) {
        List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
        myList.stream()
                .map(String::toUpperCase)
                .sorted()
                .forEach(System.out::println);
    }
}

Output:

A1
A2
B1
C1
C2

Another example to use map() to convert a list of Strings to a list of their lengths:

package org.kodejava.basic;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapStringToLength {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("Java", "Stream", "API");
        List<Integer> lengths = words
                .stream()
                .map(String::length)
                .collect(Collectors.toList());

        System.out.println("Lengths = " + lengths);
    }
}

Output:

Lengths = [4, 6, 3]
  • filter: The filter() function is used to filter out elements from a Stream based upon a Predicate. It is an intermediate operation and returns a new stream which consists of elements of the current stream which satisfies the predicate condition.

Here’s an example:

package org.kodejava.basic;

import java.util.Arrays;
import java.util.List;

public class FilterStartWith {
    public static void main(String[] args) {
        List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
        myList.stream()
                .filter(s -> s.startsWith("c"))
                .map(String::toUpperCase)
                .sorted()
                .forEach(System.out::println);
    }
}

Output:

C1
C2

Another example:

package org.kodejava.basic;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterEvenNumber {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<Integer> evens = numbers
                .stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());

        System.out.println("Even numbers = " + evens);
    }
}

Output:

Even numbers = [2, 4, 6]
  • reduce: The reduce() function takes two parameters: an initial value, and a BinaryOperator function. It reduces the elements of a Stream to a single value using the BinaryOperator, by repeated application.

Here’s an example:

package org.kodejava.basic;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class ReduceSum {
    public static void main(String[] args) {
        List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> sum = myList
                .stream()
                .reduce((a, b) -> a + b);

        sum.ifPresent(System.out::println);
    }
}

Output:

15

In the above example, the reduce method will sum all the integers in the stream and then ifPresent is simply used to print the sum if the Optional is not empty.

All these operations can be chained together to build complex data processing pipelines. Furthermore, they are “lazy”, meaning they don’t perform any computations until a terminal operation (like collect()) is invoked on the stream.

How do I combine filter and projection operation in Spring EL?

Using Spring Expression Language (SpEL) we can filter a collection based on some criteria. We can also create a projection of a collection by collecting only a particular property from the collection objects.

Now you know that you have two good features of SpEL that are really powerful to use when working with collection objects manipulation. But you are wondering how to combine both of these filters and projections in one expression. Can you do this in Spring EL? The answer is yes! You can combine them both in one expression. Let’s see an example below.

We are going to use the same configuration used in the previous example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="books">
        <bean class="org.kodejava.spring.core.el.Book" p:title="Essential C# 4.0" p:author="Michaelis" p:pages="450" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="User Stories Applied" p:author="Mike Cohen"
              p:pages="268" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Learning Android" p:author="Marco Gargenta"
              p:pages="245" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="The Ruby Programming Language"
              p:author="David Flanagan & Yukihiro Matsumoto" p:pages="250" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Einstein" p:author="Walter Isaacson" p:pages="1000" />
    </util:list>

    <bean id="library" class="org.kodejava.spring.core.el.Library">
        <property name="bookTitles" value="#{books.?[pages gt 250].![title]}" />
    </bean>

</beans>

In the configuration above, when we define the library bean we set its bookTitles property using the filtering and projection operator. First we take only books that have more than 250 pages, and then we create the projection that contains only the book title. So this expression give us all the book’s title of a book that has more than 250 pages.

To make the example complete here again the definition of the Book and the Library class.

package org.kodejava.spring.core.el;

public class Book {
    private Long id;
    private String title;
    private String author;
    private String type;
    private int pages;

    // Getters & Setters
}
package org.kodejava.spring.core.el;

import java.util.List;

public class Library {
    private List<Book> books;
    private List<String> bookTitles;

    // Getters & Setters
}

The main class the run the configuration file:

package org.kodejava.spring.core.el;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpELFilterProjectionExample {
    public static void main(String[] args) {
        try (ClassPathXmlApplicationContext context =
                     new ClassPathXmlApplicationContext("spel-filter-projection.xml")) {

            Library library = context.getBean("library", Library.class);

            for (String title : library.getBookTitles()) {
                System.out.println("title = " + title);
            }
        }
    }
}

The result of the code snippet:

title = Essential C# 4.0
title = User Stories Applied
title = Einstein

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I filter collection members based on some criteria using Spring EL?

In previous examples you have seen that we use the square-braces [] operator to select items from collection. In this post you will learn how to filter members of a collection with a certain criteria using the Spring EL. To do this Spring EL give you another special operator, the filter operator which can be typed like .?[], you can define the filter criteria inside the braces.

Beside the filter operator .?[] there are also operator that can select the first and the last matching items from collection. You can use the .^[] for selecting the first match and the .$[] operator to select the last match items from collection respectively.

As an example we will demonstrate here that we want to find a collection of books that have pages more than 250 and assign it to Library bean’s books properties. So let’s begin by defining a class called Book and Library which will have the following properties:

package org.kodejava.spring.core.el;

public class Book {
    private Long id;
    private String title;
    private String author;
    private String type;
    private int pages;

    // Getters & Setters

    @Override
    public String toString() {
        return "Book{" +
                "title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", pages=" + pages +
                '}';
    }
}
package org.kodejava.spring.core.el;

import java.util.List;

public class Library {
    private List<Book> books;

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }
}

After creating the Book and the Library class let’s now create the Spring configuration file for our demo. We will create a file and call it as spel-filter-collection.xml with the following lines of configuration in it.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="books">
        <bean class="org.kodejava.spring.core.el.Book" p:title="Essential C# 4.0" p:author="Michaelis" p:pages="450" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="User Stories Applied" p:author="Mike Cohen"
              p:pages="268" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Learning Android" p:author="Marco Gargenta"
              p:pages="245" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="The Ruby Programming Language"
              p:author="David Flanagan & Yukihiro Matsumoto" p:pages="250" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Einstein" p:author="Walter Isaacson" p:pages="1000" />
    </util:list>

    <bean id="lib1" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.?[pages gt 250]}" />
    </bean>

    <bean id="lib2" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.^[pages gt 250]}" />
    </bean>

    <bean id="lib3" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.$[pages gt 250]}" />
    </bean>

</beans>

The first thing that you can see in the configuration above is the <util-list> where we create a list of Book beans. Next we have three beans definition of the type Library where the books property was assigned with a collection of beans selected from the books list.

The lib1 will contains books that have pages more than 250. The lib2 will contains the first book found to have more than 250 pages while the lib3 will contains the last book found to have more than 250 pages.

Below is the code that will run our configuration file and the example output it will produce.

package org.kodejava.spring.core.el;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpELFilterCollection {
    public static void main(String[] args) {
        try (ClassPathXmlApplicationContext context =
                     new ClassPathXmlApplicationContext("spel-filter-collection.xml")) {

            System.out.println("Library 1");
            Library lib1 = (Library) context.getBean("lib1");
            for (Book book : lib1.getBooks()) {
                System.out.println("    Book = " + book);
            }

            System.out.println("Library 2");
            Library lib2 = (Library) context.getBean("lib2");
            for (Book book : lib2.getBooks()) {
                System.out.println("    Book = " + book);
            }

            System.out.println("Library 3");
            Library lib3 = (Library) context.getBean("lib3");
            for (Book book : lib3.getBooks()) {
                System.out.println("    Book = " + book);
            }
        }
    }
}
Library 1
    Book = Book{title='Essential C# 4.0', author='Michaelis', pages=450}
    Book = Book{title='User Stories Applied', author='Mike Cohen', pages=268}
    Book = Book{title='Einstein', author='Walter Isaacson', pages=1000}
Library 2
    Book = Book{title='Essential C# 4.0', author='Michaelis', pages=450}
Library 3
    Book = Book{title='Einstein', author='Walter Isaacson', pages=1000}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I set a filter on a logger handler?

This example give you an example on how to set the Filter of a logger handler. In the code below we implement the Filter on the FileHandler to log only a Level.SEVERE message. Other log level will not be recorded to the file.

package org.kodejava.util.logging;

import java.util.logging.*;
import java.io.IOException;

public class LoggerFilter {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(LoggerFilter.class.getName());

        FileHandler handler = null;
        try {
            handler = new FileHandler("myapp.log");
            // The message will be recorded to the file When the 
            // LogRecord level is equals to Level.SEVERE
            handler.setFilter(record -> record.getLevel().equals(Level.SEVERE));
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Fail to create logger handler", e);
        }

        logger.addHandler(handler);

        logger.info("Information message");
        logger.warning("Warning message");
        logger.severe("Severe message");
    }
}