java - Java8: Filter and compare 2 Lists with Lambda -


the task:

i have 2 lists contains of entrys (id + datetime) id's can multiple differen datetimes.

i need list of id's whith following conditions:

  • the id of list1 not in list2
  • if id of list1 in list2, see if has higher date
  • if id of list1 has higher count in list2

the question: how can java 8 streams?

examplecode:

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: list of id's list1 have higher date or doesnt exists in list2          // filter list1 every id unique (with highest date)         final map<integer, datetime> list1uniqueidmap = new hashmap<integer, datetime>();         (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 every id unique (with highest date)         final map<integer, datetime> list2uniqueidmap = new hashmap<integer, datetime>();         (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);          // list of id's in list1 not in list2, or, if in list2, if have higher date         // furthermore, the id's of list1 have higher count in list2         final set<integer> resultset = new hashset<integer>();         (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;         (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() + "]";         }      } } 

output of example:

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] 

first, want create intermediate map<integer, datetime> list2 each entry's id mapped maximum date. way, have compare each id list1 maximum date see if after or not.

to consider update need keep ids have higher count of list1 in list2, need create 2 map<integer, long> stores count each id list1 , list2

creating map can done grouping list2 entry's id. using groupingby(classifier, downstream) classifier being method-reference entry::getid returning id of entry. downstream collector used collect value having same id single result; in case, using maxby collector comparing each entry's date comparing(keyextractor). since comparator returns optional (to handle case have noting collect, no maximum value), wrapped collectingandthen applies finisher operation which, in case, gets optional value , retrieve date it. idea same count map, difference time, downstream collector counting() counts number of values having same key.

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())); 

having intermediate map, can filter list1: keep elements map not contain current id, or if does, current entry's date after 1 stored in map. since we're not interested in duplicates, collected set.

set<integer> ids =     list1.stream()          .filter(e -> !mapdate.containskey(e.getid()) ||                        e.getdate().isafter(mapdate.get(e.getid())) ||                       mapcount1.get(e.getid()) > mapcount2.get(e.getid()))          .map(entry::getid)          .collect(toset()); 

static imports used make code cleaner:

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; 

Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

javascript - Get parameter of GET request -

javascript - Twitter Bootstrap - how to add some more margin between tooltip popup and element -