Java 8 collector for Guava immutable collections? -
i java 8 streams , guava's immutable collections, can't figure out how use 2 together.
for example, how implement java 8 collector gathers stream results immutablemultimap?
bonus points: i'd able provide key/value mappers, similar how collectors.tomap() works.
update: found implementation seems cover guava collections @ https://github.com/yanaga/guava-stream , attempted improve upon in own library @ https://bitbucket.org/cowwoc/guava-jdk8/
i'm leaving previous answer below, historical reasons.
holy #@!( got it!
this implementation works multimap (mutable or immutable) whereas shmosel's solution focuses on immutable implementations. said, latter might more efficient immutable case (i don't use builder).
import com.google.common.collect.multimap; import java.util.enumset; import java.util.set; import java.util.function.biconsumer; import java.util.function.binaryoperator; import java.util.function.function; import java.util.function.supplier; import java.util.stream.collector; import java.util.stream.collector.characteristics; import org.bitbucket.cowwoc.preconditions.preconditions; /** * stream collector returns multimap. * <p> * @author gili tzabari * @param <t> type of input elements * @param <k> type of keys stored in map * @param <v> type of values stored in map * @param <r> output type of collector */ public final class multimapcollector<t, k, v, r extends multimap<k, v>> implements collector<t, multimap<k, v>, r> { private final supplier<multimap<k, v>> mapsupplier; private final function<? super t, ? extends k> keymapper; private final function<? super t, ? extends v> valuemapper; private final function<multimap<k, v>, r> resultmapper; /** * creates new multimapcollector. * <p> * @param mapsupplier function returns new, empty {@code multimap} intermediate results * inserted * @param keymapper function transforms map keys * @param valuemapper function transforms map values * @param resultmapper function transforms intermediate {@code multimap} final result * @throws nullpointerexception if of arguments null */ public multimapcollector(supplier<multimap<k, v>> mapsupplier, function<? super t, ? extends k> keymapper, function<? super t, ? extends v> valuemapper, function<multimap<k, v>, r> resultmapper) { preconditions.requirethat(mapsupplier, "mapsupplier").isnotnull(); preconditions.requirethat(keymapper, "keymapper").isnotnull(); preconditions.requirethat(valuemapper, "valuemapper").isnotnull(); preconditions.requirethat(resultmapper, "resultmapper").isnotnull(); this.mapsupplier = mapsupplier; this.keymapper = keymapper; this.valuemapper = valuemapper; this.resultmapper = resultmapper; } @override public supplier<multimap<k, v>> supplier() { return mapsupplier; } @override public biconsumer<multimap<k, v>, t> accumulator() { return (map, entry) -> { k key = keymapper.apply(entry); if (key == null) throw new illegalargumentexception("keymapper(" + entry + ") returned null"); v value = valuemapper.apply(entry); if (value == null) throw new illegalargumentexception("keymapper(" + entry + ") returned null"); map.put(key, value); }; } @override public binaryoperator<multimap<k, v>> combiner() { return (left, right) -> { left.putall(right); return left; }; } @override public function<multimap<k, v>, r> finisher() { return resultmapper; } @override public set<characteristics> characteristics() { return enumset.noneof(characteristics.class); } }
[...]
import com.google.common.collect.hashmultimap; import com.google.common.collect.immutablemultimap; import com.google.common.collect.multimap; import java.util.function.function; import java.util.function.supplier; import java.util.stream.collector; /** * stream collectors guava collections. * <p> * @author gili tzabari */ public final class guavacollectors { /** * returns {@code collector} accumulates elements {@code multimap}. * <p> * @param <t> type of input elements * @param <k> type of map keys * @param <v> type of map values * @param <r> output type of collector * @param mapsupplier function returns new, empty {@code multimap} intermediate results * inserted * @param keymapper function transforms map keys * @param valuemapper function transforms map values * @param resultmapper function transforms intermediate {@code multimap} final result * @return {@code collector} collects elements {@code multimap} keys , values result of * applying mapping functions input elements */ public static <t, k, v, r extends multimap<k, v>> collector<t, ?, r> tomultimap( supplier<multimap<k, v>> mapsupplier, function<? super t, ? extends k> keymapper, function<? super t, ? extends v> valuemapper, function<multimap<k, v>, r> resultmapper) { return new multimapcollector<>(mapsupplier, keymapper, valuemapper, resultmapper); } public static void main(string[] args) { multimap<integer, double> input = hashmultimap.create(); input.put(10, 20.0); input.put(10, 25.0); input.put(50, 60.0); system.out.println("input: " + input); immutablemultimap<integer, double> output = input.entries().stream().collect( guavacollectors.tomultimap(hashmultimap::create, entry -> entry.getkey() + 1, entry -> entry.getvalue() - 1, immutablemultimap::copyof)); system.out.println("output: " + output); } }
main() outputs:
input: {10=[20.0, 25.0], 50=[60.0]} output: {51=[59.0], 11=[24.0, 19.0]}
resources
- arjit provided excellent resource demonstrating how implement collectors other guava collections: http://blog.comsysto.com/2014/11/12/java-8-collectors-for-guava-collections/
Comments
Post a Comment