Java8:使用Lambda筛选并比较2个列表

Java8:使用Lambda筛选并比较2个列表,java,java-8,java-stream,Java,Java 8,Java Stream,任务: 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

任务:

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<Entry> 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<Entry> 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<Integer, DateTime> list1UniqueIdMap = new HashMap<Integer, DateTime>();
        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<Integer, DateTime> list2UniqueIdMap = new HashMap<Integer, DateTime>();
        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<Integer> resultSet = new HashSet<Integer>();
        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) > getCount(list2, id))
            {
                resultSet.add(id);
            }
        }

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

    private int getCount(final List<Entry> 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() + "]";
        }

    }
}
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]
我有两个包含入口的列表(Id+DateTime) ID可以是多个,具有不同的日期时间

我需要具有以下条件的ID列表:

  • 列表1的id不在列表2中
  • 如果列表1的id在列表2中,请查看它是否有更高的日期
  • 如果列表1的id在列表2中的计数较高
问题: 如何使用Java8流实现这一点

示例代码:

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<Entry> 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<Entry> 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<Integer, DateTime> list1UniqueIdMap = new HashMap<Integer, DateTime>();
        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<Integer, DateTime> list2UniqueIdMap = new HashMap<Integer, DateTime>();
        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<Integer> resultSet = new HashSet<Integer>();
        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) > getCount(list2, id))
            {
                resultSet.add(id);
            }
        }

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

    private int getCount(final List<Entry> 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() + "]";
        }

    }
}
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]

首先,您需要从
list2
创建一个中间
Map
,其中每个条目的id映射到最大日期。这样,我们只需将
list1
中的每个id与这个最大日期进行比较,看看它是否在之后

考虑您的更新,您还需要保持比 List1更高的代码的ID,我们还需要创建另外两个<代码> map < /COD>,存储每个ID的计数为<代码> List1和<代码> List2

创建此映射可以通过使用条目id对
list2
进行分组来完成。我们使用的分类器是返回条目id的方法引用
entry::getId
。下游收集器用于将具有相同id的所有值收集到单个结果中;在本例中,我们使用的收集器比较每个条目的日期。由于此比较器返回一个
可选的
(用于处理需要收集注释的情况,因此没有最大值),因此它被包装到一个应用finisher操作的函数中,在这种情况下,该函数获取可选值并从中检索日期。计数映射的思想是相同的,不同的是,这一次,下游收集器对具有相同键的值的数量进行计数

Map<Integer, DateTime> map =
    list2.stream()
         .collect(groupingBy(
             Entry::getId,
             collectingAndThen(maxBy(comparing(Entry::getDate)), e -> e.get().getDate())
         ));

Map<Integer, Long> mapCount2 = list2.stream().collect(groupingBy(Entry::getId, counting()));
Map<Integer, Long> mapCount1 = list1.stream().collect(groupingBy(Entry::getId, counting()));

用于使代码更干净的静态导入:

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.maxBy;
import static java.util.stream.Collectors.toSet;

我将使用身份函数为
valueMapper
toMap
list2
创建一个从id到date的映射。然后使用
e->上的
filter
list1
进行过滤!map.containsKey(e.id)| e.isAfter(map.get(e.id))
。添加
.map(e->e.id)
如果你想要一个id的集合。我对lambda是完全陌生的。可能需要完整的代码。如果你对lambdas完全陌生,我建议你去读一本教程,而不是发帖或让别人为你写代码。我读教程。但我最好用一个具体的例子来学习。非常感谢!很好用!