@@ -110,27 +110,33 @@ public WithKeys<K, V> withKeyType(TypeDescriptor<K> keyType) {
110110
111111 @ Override
112112 public PCollection <KV <K , V >> expand (PCollection <V > in ) {
113+ SerializableFunction <V , K > localFn = fn ;
114+ TypeDescriptor <V > inputType = in .getTypeDescriptor ();
115+ TypeDescriptor <KV <K , V >> outputType = getOutputTypeDescriptor (inputType );
113116 PCollection <KV <K , V >> result =
114117 in .apply (
115118 "AddKeys" ,
116- MapElements .via (
117- new SimpleFunction <V , KV <K , V >>() {
118- @ Override
119- public KV <K , V > apply (V element ) {
120- return KV .of (fn .apply (element ), element );
121- }
122- }));
119+ outputType == null
120+ ? MapElements .via (
121+ new SimpleFunction <V , KV <K , V >>() {
122+ @ Override
123+ public KV <K , V > apply (V element ) {
124+ return KV .of (localFn .apply (element ), element );
125+ }
126+ })
127+ : MapElements .into (outputType )
128+ .via (
129+ (SerializableFunction <V , KV <K , V >>)
130+ element -> KV .of (localFn .apply (element ), element )));
123131
124132 try {
125- Coder <K > keyCoder ;
126133 CoderRegistry coderRegistry = in .getPipeline ().getCoderRegistry ();
127- if (keyType == null ) {
128- keyCoder = coderRegistry .getOutputCoder (fn , in .getCoder ());
134+ if (outputType == null ) {
135+ Coder <K > keyCoder = coderRegistry .getOutputCoder (fn , in .getCoder ());
136+ result .setCoder (KvCoder .of (keyCoder , in .getCoder ()));
129137 } else {
130- keyCoder = coderRegistry .getCoder (keyType );
138+ result . setCoder ( coderRegistry . getCoder ( outputType , checkNotNull ( inputType ), in .getCoder ()) );
131139 }
132- // TODO: Remove when we can set the coder inference context.
133- result .setCoder (KvCoder .of (keyCoder , in .getCoder ()));
134140 } catch (CannotProvideCoderException exc ) {
135141 if (keyType != null ) {
136142 try {
@@ -151,4 +157,12 @@ public KV<K, V> apply(V element) {
151157
152158 return result ;
153159 }
160+
161+ private @ Nullable TypeDescriptor <KV <K , V >> getOutputTypeDescriptor (
162+ @ Nullable TypeDescriptor <V > inputType ) {
163+ if (keyType == null || inputType == null ) {
164+ return null ;
165+ }
166+ return TypeDescriptors .kvs (keyType , inputType );
167+ }
154168}
0 commit comments