Java8: Filter and compare 2 Lists with Lambda
<p><strong>The task:</strong></p>

<p>I have 2 Lists which contains of Entrys (Id + DateTime)
The ID's can be multiple with differen DateTimes.</p>

<p>I need a List of ID's whith the following conditions:</p>

<ul>
<li>the id of list1 is not in list2</li>
<li>if the id of list1 is in list2, see if it has a higher date</li>
<li>if the id of list1 has an higher count the in list2</li>
</ul>

<p><strong>The question:</strong>
How can I do this with Java 8 Streams?</p>

<p><strong>ExampleCode:</strong></p>

<pre><code>import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

public class LambdaFilter
{
    public static void main(final String[] args)
    {
        final LambdaFilter lf = new LambdaFilter();
        lf.start();
    }

    private void start()
    {
        final List&lt;Entry&gt; list1 = Arrays.asList(
                                                new Entry(15, new DateTime(2012, 6, 29, 0, 0, 0, 0)),
                                                new Entry(101, new DateTime(2012, 3, 12, 0, 0, 0, 0)),
                                                new Entry(101, new DateTime(2012, 3, 12, 0, 0, 0, 0)),
                                                new Entry(68691, new DateTime(2015, 2, 12, 0, 0, 0, 0)),
                                                new Entry(68691, new DateTime(2015, 2, 12, 0, 0, 0, 0)),
                                                new Entry(68691, new DateTime(2015, 5, 01, 0, 0, 0, 0)),
                                                new Entry(70738, new DateTime(2016, 1, 26, 0, 0, 0, 0)));
        final List&lt;Entry&gt; list2 = Arrays.asList(
                                                new Entry(15, new DateTime(2012, 6, 29, 0, 0, 0, 0)),
                                                new Entry(101, new DateTime(2012, 3, 12, 0, 0, 0, 0)),
                                                new Entry(68691, new DateTime(2015, 2, 12, 0, 0, 0, 0)),
                                                new Entry(68691, new DateTime(2015, 2, 12, 0, 0, 0, 0)),
                                                new Entry(70738, new DateTime(2015, 7, 30, 0, 0, 0, 0)));

        System.out.println(list1);
        System.out.println(list2);

        // MAIN-GOAL: Get a list of ID's from list1 which have a higher Date or doesnt exists in list2

        // Filter list1 so every ID is unique (with highest Date)
        final Map&lt;Integer, DateTime&gt; list1UniqueIdMap = new HashMap&lt;Integer, DateTime&gt;();
        for (final Entry e : list1)
        {
            if (!list1UniqueIdMap.containsKey(e.getId()))
            {
                list1UniqueIdMap.put(e.getId(), e.getDate());
            }
            else
            {
                final DateTime dateFromMap = list1UniqueIdMap.get(e.getId());
                if (e.getDate().isAfter(dateFromMap))
                {
                    list1UniqueIdMap.put(e.getId(), e.getDate());
                }
            }
        }

        // Filter list2 so every ID is unique (with highest Date)
        final Map&lt;Integer, DateTime&gt; list2UniqueIdMap = new HashMap&lt;Integer, DateTime&gt;();
        for (final Entry e : list2)
        {
            if (!list2UniqueIdMap.containsKey(e.getId()))
            {
                list2UniqueIdMap.put(e.getId(), e.getDate());
            }
            else
            {
                final DateTime dateFromMap = list2UniqueIdMap.get(e.getId());
                if (e.getDate().isAfter(dateFromMap))
                {
                    list2UniqueIdMap.put(e.getId(), e.getDate());
                }
            }
        }

        System.out.println(list1UniqueIdMap);
        System.out.println(list2UniqueIdMap);

        // Get List of ID's which are in list1 but not in list2, or, if they are in list2, if they have a higher date
        // Furthermore, the the ID's of list1 which have a higher count then in list2
        final Set&lt;Integer&gt; resultSet = new HashSet&lt;Integer&gt;();
        for (final Integer id : list1UniqueIdMap.keySet())
        {
            if (!list2UniqueIdMap.containsKey(id))
            {
                resultSet.add(id);
            }
            else
            {
                final DateTime dateList1 = list1UniqueIdMap.get(id);
                final DateTime dateList2 = list2UniqueIdMap.get(id);

                if (dateList1.isAfter(dateList2))
                {
                    resultSet.add(id);
                }
            }

            if (getCount(list1, id) &gt; getCount(list2, id))
            {
                resultSet.add(id);
            }
        }

        // Result
        System.out.println(resultSet);
    }

    private int getCount(final List&lt;Entry&gt; list, final int id)
    {
        int count = 0;
        for (final Entry e : list)
        {
            if (e.getId() == id)
            {
                count++;
            }
        }
        return count;
    }

    private class Entry
    {
        private int id;
        private DateTime date;

        public Entry(final int id, final DateTime date)
        {
            this.id = id;
            this.date = date;
        }

        public int getId()
        {
            return id;
        }

        public void setId(final int id)
        {
            this.id = id;
        }

        public DateTime getDate()
        {
            return date;
        }

        public String getFormattedLastChangeDat()
        {
            return DateTimeFormat.forPattern("dd.MM.yyyy").print(getDate());
        }

        public void setDate(final DateTime date)
        {
            this.date = date;
        }

        @Override
        public String toString()
        {
            return this.getClass().getSimpleName() + "[id: " + this.getId() + " , date: " + this.getFormattedLastChangeDat() + "]";
        }

    }
}
</code></pre>

<p><strong>Output of my Example:</strong></p>

<pre><code>List1
[
Entry[id: 15 , date: 29.06.2012], 
Entry[id: 101 , date: 13.03.2012], 
Entry[id: 101 , date: 13.03.2012],   
Entry[id: 68691 , date: 12.02.2015],   
Entry[id: 68691 , date: 12.02.2015],   
Entry[id: 68691 , date: 01.05.2015],   
Entry[id: 70738 , date: 26.01.2016]]

List2:  
[
Entry[id: 15 , date: 29.06.2012],  
Entry[id: 101 , date: 13.03.2012],  
Entry[id: 68691 , date: 12.02.2015],   
Entry[id: 68691 , date: 12.02.2015],   
Entry[id: 70738 , date: 30.07.2015]]

List1UniqueIdMap:  
{
101=2012-03-12T00:00:00.000+01:00,
70738=2016-01-26T00:00:00.000+01:00,     
68691=2015-05-01T00:00:00.000+02:00,       
15=2012-06-29T00:00:00.000+02:00}

List2UniqueIdMap:  
{
101=2012-03-12T00:00:00.000+01:00,
70738=2015-07-30T00:00:00.000+02:00,     
68691=2015-02-12T00:00:00.000+01:00,     
15=2012-06-29T00:00:00.000+02:00}

Result:  
[101, 68691, 70738]
</code></pre>