title: How to perform filtering by Key on KeyValue objects using Lambda-Expressions?
body: <p>Given i want to filter a List of Key-Value objects.</p>
  
  <p>My (Document)-Object from the example below looks like this</p>
  
  
  
  <pre><code>{
      "attributeEntityList" : [
          {key: 'key1', value: 'somevalue1'},
          {key: 'key2', value: 'somevalue2'},
          {key: 'key3', value: 'somevalue3'}
      ]
  }
  </code></pre>
  
  <ol>
  <li><p>When I pass in a list of the following keys <code>["key1", "key2", "key3"]</code>, I expect my function to return the whole given List of attributes.</p></li>
  <li><p>When I pass in a list of the following keys <code>["key1", "key2"]</code>, I expect my function to return a list of Attributes with the given key-names.</p></li>
  <li><p>When I pass in a list of the following keys <code>["key1", "key2", "faultyKey"]</code>, I expect my function to return an Empty list.</p></li>
  </ol>
  
  <p>My imperative-style solution looks like this and it works okay:</p>
  
  <pre class="lang-java prettyprint-override"><code>private List&lt;AttributeEntity&gt; getAttributeEntities(List&lt;String&gt; keys, Document value) {
      final List&lt;AttributeEntity&gt; documentAttributeList = value.getAttributeEntityList();
      final List&lt;AttributeEntity&gt; resultList = new ArrayList&lt;&gt;();
  
      for(String configKey: keys){
          boolean keyInAttribute = false;
          for(AttributeEntity documentAttribute : documentAttributeList){
              if(configKey.equals(documentAttribute.getAttribute_key())){
                  keyInAttribute = true;
                  resultList.add(documentAttribute);
                  break;
              }
          }
          if(!keyInAttribute){
              resultList.clear();
              break;
          }
      }
  
      return resultList;
  }
  </code></pre>
  
  <p>For education and fun (and maybe better scaling) I'd like to know how to convert this piece of Code into a solution using the new Java 8 streaming-api.</p>
  
  <hr>
  
  <p>This is what I came up with, converting my pre-Java8-code to Java8.</p>
  
  <p>To my eyes it looks much more concise and it's shorter. But it does not, what I expect it to do :/</p>
  
  <p>I'm realy struggling implementing the third bulletpoint of my requirements.
  It always returns all (found) Attributes, even when i pass in a not existant key.</p>
  
  <pre class="lang-java prettyprint-override"><code>private List&lt;AttributeEntity&gt; getAttributeEntities(List&lt;String&gt; keys, Document value) {
      final List&lt;AttributeEntity&gt; documentAttributeList = value.getAttributeList();
  
      return documentAttributeList.stream()
              .filter(attribute -&gt;
                      keys.contains(attribute.getAttribute_key())
              ).collect(Collectors.toList());
  }
  </code></pre>
  
  <p>I'm thinking of implementing my own custom Collector.
  Since my Collector should only return the List, when the collected results contain each given key at least once.</p>
  
  <p>Any other Idea on how to achieve that?</p>
  
  <hr>
  
  <p>This solution passes my tests.
  But it feel's like i'm putting the cart before the horse.</p>
  
  <p>It's neither concise nor short or elegant any more.</p>
  
  <pre class="lang-java prettyprint-override"><code>private List&lt;AttributeEntity&gt; getAttributeEntities(List&lt;String&gt; keys, Document value) {
      final List&lt;AttributeEntity&gt; documentAttributeList = value.getAttributeList();
  
      return documentAttributeList.stream()
              .filter(attribute -&gt;
                              keys.contains(attribute.getAttribute_key())
              )
              .collect(Collectors.collectingAndThen(Collectors.toList(), new Function&lt;List&lt;AttributeEntity&gt;, List&lt;AttributeEntity&gt;&gt;() {
                  @Override
                  public List&lt;AttributeEntity&gt; apply(List&lt;AttributeEntity&gt; o) {
                      System.out.println("in finisher code");
                      if (keys.stream().allMatch(key -&gt; {
                          return o.stream().filter(attrbiute -&gt; attrbiute.getAttribute_key().equals(key)).findAny().isPresent();
                      })) {
                          return o;
                      } else {
                          return new ArrayList&lt;AttributeEntity&gt;();
                      }
                  }
              }));
  }
  </code></pre>