the question pretty in title. i'm looking algorithm more efficient full search through collections.
i have 2 collections:
list<map<typeid, object> > col1; list<entity> col2;
where
public enum typeid{ player, partner, platform, amount }
and
public class entity{ private int player_id; private int platform_id private bigdecimal amount; //get, set }
the col1
collection of type list<map<typeid, object> >
contains player, partner, platform
typeid
s.
i need write method:
public list<map<typeid, object> > merge(list<map<typeid, object> > col1, list<entity> col2){ //impl }
which going produce list<map<typeid, object> >
each entry entry
of map contains additional key-value (amount, amount's value)
amount's value
value of amount
field of instance e
of entity
if e.player_id = entry.get(player) && e.platform_id = entry.get(platform)
, null
otherwise.
in fact, operation same as
col1 left outer join col2 on e.player_id = entry.get(player) && e.platform_id = entry.get(platform)
sample:
col1: [{platform: 1, partner: 1, player: 1}, {platform: 1, partner: 3, player: 1}, {platform: 2, partner: 1, player: 2} {platform: 3, partner: 4, player: 5}] col2: [entity(platform_id = 1, player_id = 1, amount = 100), entity(platform_id = 2, player_id = 2, amount = 200), entity(platform_id = 3, player_id = 4, amount = 300)] result: [{platform: 1, partner: 1, player: 1, amount: 100}, {platform: 1, partner: 3, player: 1, amount: 100}, {platform: 2, partner: 1, player: 2, amount: 200}, {platform: 3, partner: 4, player: 5, amount: null}]
it's easier make changes in-place, modifying col1
list instead of creating new list
. here's java-8 solution:
public list<map<typeid, object> > merge(list<map<typeid, object> > col1, list<entity> col2){ col1.foreach(map -> map.put(typeid.amount, col2.stream() .filter(e -> e.player_id == (int)map.get(typeid.player) && e.platform_id == (int)map.get(typeid.platform)) .findfirst().map(e -> e.amount).orelse(null) )); return col1; }
i suppose changing col1
in place satisfactory in case. note if store result new list, useless if modify existing maps. make result totally independent col1
, have copy maps.
also note it's not effective each col1
entry traverses col2
, complexity col1.size()*col2.size()
. it's better in case throw away entity
class , create new 1 stores platformid , playerid (with implemented equals
, hashcode
) , use map key:
public static class platformandplayer { private final int playerid, platformid; public platformandplayer(int playerid, int platformid) { this.playerid = playerid; this.platformid = platformid; } @override public int hashcode() { final int prime = 31; int result = 1; result = prime * result + platformid; result = prime * result + playerid; return result; } @override public boolean equals(object obj) { if (this == obj) return true; if (obj == null) return false; if (getclass() != obj.getclass()) return false; platformandplayer other = (platformandplayer) obj; if (platformid != other.platformid) return false; if (playerid != other.playerid) return false; return true; } }
this way instead of col2
list have map
:
map<platformandplayer, bigdecimal> col2 = new hashmap<>(); col2.put(new platformandplayer(1, 1), bigdecimal.valueof(100)); col2.put(new platformandplayer(2, 2), bigdecimal.valueof(200)); col2.put(new platformandplayer(3, 4), bigdecimal.valueof(300));
now task can solved , (even java 5):
public static list<map<typeid, object>> merge( list<map<typeid, object>> col1, map<platformandplayer, bigdecimal> col2) { (map<typeid, object> map : col1) { map.put(typeid.amount, col2.get(new platformandplayer( (int) map.get(typeid.player), (int) map.get(typeid.platform)))); } return col1; }
Comments
Post a Comment