Python's ChainMap for Java? -
i have nested configuration hassle.
the problem happens in machine learning, end-user calling cross-validation routine, may, or may not specify of various parameters (e.g. "randomseed" = 17)
either way, parameters have passed first cross-validation algorithm, , on first machine learning algorithm. machine learning algorithm, must able set , pass on other parameters, without initial user knowing.
most of consumers in chain of parameter users expect java map interface doing look-up from.
flattening keys 1 library unattractive performance reasons -- both cpu , memory -- (the 'root key-name' space) used without modification many thousands of times, , each time number of additional parameters need specified before bundle passed along.
a decent analog how path variable works, each element in path being directory (key-namespace). when query made against path variable (eg. type 'emacs' @ command line), looks in each directory (unnamed namespace of keys) file-name (specified value) in order, until either finds it, or fails find it. if finds it, execute specific contents of executable file found (get value of parameter set). if have path variable another, can append new directory (anonymous key-space ) in front of pass path variable setting along new end-user, without modifying previous directories (preferences).
given name-space on configuration parameters flat, solution python's chainmap perfect (eg example usage) i'm finding no equivalent solution in java?
over weekend went ahead , created chainmap
implementation well; java 8 it's surprisingly small class. implementation different yours; doesn't attempt mirror python's behavior , instead follows map
interface's specifications. notably:
- lookup order insertion order; first map passed constructor takes precedence on following maps.
.containsvalue()
doesn't match values masked earlier maps..put()
returns previous value of chain map, if value in later map..remove()
removes key maps, not first map or visible entry. javadoc: "the map not contain mapping specified key once call returns."- similarly
.clear()
clears maps, not top map. - implements
.equals()
,.hashcode()
on basis of entry set, equal othermap
implementations.
i did not implement push/pop behavior felt anti-pattern; chainmap
o(1) view series of maps, can construct additional chainmap
s maps want needed.
obviously, if implementation works use case, that's great. violates map
contract in several places; i'd suggest removing implements map<k, v>
, let standalone class.
many of class's methods nice one-liners, e.g.:
@override public int size() { return keyset().size(); } @override public boolean isempty() { return !chain.stream().filter(map -> !map.isempty()).findfirst().ispresent(); } @override public boolean containskey(object key) { return chain.stream().filter(map -> map.containskey(key)).findfirst().ispresent(); } @override public boolean containsvalue(object value) { return entryset().stream() .filter(e -> value == e.getvalue() || (value != null && value.equals(e.getvalue()))) .findfirst().ispresent(); } @override public v get(object key) { return chain.stream().filter(map -> map.containskey(key)) .findfirst().map(map -> map.get(key)).orelse(null); }
i've written tests verify class's behavior well. additional test cases welcome.
i extended idea of using maps.asmap()
create immutable view of collection of maps; if don't need mutation work nicely. (as i learned, have use three-argument form of .reduce()
generics behave).
public static <k, v> map<k, v> immutablechainview( iterable<? extends map<? extends k, ? extends v>> maps) { return streamsupport.stream(maps.spliterator(), false).reduce( (map<k,v>)immutablemap.<k,v>of(), (a, b) -> maps.asmap(sets.union(a.keyset(), b.keyset()), k -> a.containskey(k) ? a.get(k) : b.get(k)), (a, b) -> maps.asmap(sets.union(a.keyset(), b.keyset()), k -> a.containskey(k) ? a.get(k) : b.get(k))); }
Comments
Post a Comment