title: How to convert if-else if chaining block code with multiple filter criteria into single filter criteria with null check?
body: <p>I do have a <code>Employee</code> class &amp; there is a method <code>getEmployees()</code> which returns all possible employees. I want to add multiple filter criteria on the same along with different <code>and</code> conditions only if incoming params are <code>not null</code>.</p>
  
  <p>I've tried following approach which do the filtering part but there are multiple if-else if chaining is happening. Is there any better way to reduce this chaining into single predicate something similar done in <a href="https://stackoverflow.com/a/22855465/1995161">dynamic filtering</a>. The chaining code I've is as follow:</p>
  
  <p>Employee class</p>
  
  <pre><code>public class Employee{
      private String fName;
      private String lName;
      private String type;
  
      //getters &amp; setters
  
  }
  </code></pre>
  
  <p>If-else if chaining block:</p>
  
  <pre><code>public List&lt;Employee&gt; retrieveEmployees(String searchToken, String fName, String lName, String type){
      //this will retrieve all the available employees 
      List&lt;Employee&gt; employees = getEmployees(); 
      List&lt;Employee&gt; filteredEmployees= new ArrayList&lt;&gt;();
  
      //perform filtering on the basis of accepted params
      if(searchToken !=null){
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getFName().equalsIgnoreCase(searchToken) &amp;&amp; emp.getLName().equalsIgnoreCase(searchToken))
          .collect(Collectors.toList());
  
      }
      else if (fName != null &amp;&amp; lName != null &amp;&amp; type != null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getFName().equalsIgnoreCase(fName) &amp;&amp; emp.getLName().equalsIgnoreCase(lName) &amp;&amp; emp.getType().equalsIgnoreCase(type))
          .collect(Collectors.toList());
      } else if (type != null &amp;&amp; fname != null &amp;&amp; lname == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getFName().equalsIgnoreCase(fName) &amp;&amp; emp.getType().equalsIgnoreCase(type))
          .collect(Collectors.toList());
      } else if (fname != null &amp;&amp; lname != null &amp;&amp; type == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getFName().equalsIgnoreCase(fName) &amp;&amp; emp.getLName().equalsIgnoreCase(lName))
          .collect(Collectors.toList());
      } else if (lname != null &amp;&amp; type != null &amp;&amp; fname == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getLName().equalsIgnoreCase(lName) &amp;&amp; emp.getType().equalsIgnoreCase(type))
          .collect(Collectors.toList());
      } else if (fname != null &amp;&amp; lname == null &amp;&amp; type == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getFName().equalsIgnoreCase(fName))
          .collect(Collectors.toList());
      } else if (lname != null &amp;&amp; fname == null &amp;&amp; type == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getLName().equalsIgnoreCase(lName))
          .collect(Collectors.toList());
      } else if (type != null &amp;&amp; fname == null &amp;&amp; lname == null) {
          filteredEmployees=employees
          .stream()
          .filter(emp-&gt; emp.getType().equalsIgnoreCase(type))
          .collect(Collectors.toList());
      } else {
          filteredEmployees=getEmployees();
      }
  
  
      return filteredEmployees;
  }
  </code></pre>
  
  <p>I've tried something like, but it fails as predicate itself is just doing <code>or/and</code> it doesn't satisfy what I've done in <code>if-else if</code> block:</p>
  
  <pre><code>List&lt;Predicate&lt;Employee&gt;&gt; predicates=Arrays.asList(
              e -&gt; e.getFName().equalsIgnoreCase(fName),
              e -&gt; e.getLName().equalsIgnoreCase(lName),
              e -&gt; e.getType().equals(type)
      );
  
  Predicate&lt;Employee&gt; compositePredicate = predicates
      .stream()
      .reduce(w -&gt; true, Predicate::or); //tried with 'and' as well
  
  filteredEmployees= employees
      .stream()
      .filter(compositePredicate)
      .collect(Collectors.toList());
  </code></pre>
  
  <p>What I'm missing in it ? What's efficient stream predicate chaining approach can be applied ?</p>