<p>This is an attempt to justify the rationale of Spark here, and it should be read as a complement to the nice <em>programming</em> explanation already provided as an answer...</p>

<p>To start with, how exactly individual word embeddings should be combined is not in principle a feature of the Word2Vec model itself (which is about, well, <em>individual</em> words), but an issue of concern to "higher order" models, such as <a href="https://github.com/klb3713/sentence2vec" rel="noreferrer">Sentence2Vec</a>, Paragraph2Vec, <a href="https://radimrehurek.com/gensim/models/doc2vec.html" rel="noreferrer">Doc2Vec</a>, <a href="https://wikipedia2vec.github.io/wikipedia2vec/" rel="noreferrer">Wikipedia2Vec</a> etc (you could name a few more, I guess...).</p>

<p>Having said that, it turns out indeed that a very first approach in combining word vectors in order to get vector representations of larger pieces of text (phrases, sentences, tweets etc) is indeed to simply average the vector representations of the constituent words, as Spark ML does. </p>

<p>Starting from the practitioner community, we have:</p>

<p><a href="https://stackoverflow.com/questions/36731784/wordvectors-how-to-concatenate-word-vectors-to-form-sentence-vector">How to concatenate word vectors to form sentence vector</a> (SO answer):</p>

<blockquote>
  <p>There are at least three common ways to combine embedding vectors; (a)
  summing, (b) summing &amp; averaging or (c) concatenating. [...] See <code>gensim.models.doc2vec.Doc2Vec</code>, <code>dm_concat</code> and
  <code>dm_mean</code> - it allows you to use any of those three options</p>
</blockquote>

<p><a href="https://medium.com/@premrajnarkhede/sentence2vec-evaluation-of-popular-theories-part-i-simple-average-of-word-vectors-3399f1183afe" rel="noreferrer">Sentence2Vec : Evaluation of popular theories — Part I (Simple average of word vectors)</a> (blog post):</p>

<blockquote>
  <p>So what’s first thing that comes to your mind when you have word
  vectors and need to calculate sentence vector.</p>
  
  <p>Just average them?</p>
  
  <p>Yes that’s what we are going to do here.
  <a href="https://i.stack.imgur.com/878in.png" rel="noreferrer"><img src="https://i.stack.imgur.com/878in.png" alt="enter image description here"></a></p>
</blockquote>

<p><a href="https://github.com/stanleyfok/sentence2vec" rel="noreferrer">Sentence2Vec</a> (Github repo):</p>

<blockquote>
  <p>Word2Vec can help to find other words with similar semantic meaning.
  However, Word2Vec can only take 1 word each time, while a sentence
  consists of multiple words. To solve this, I write the Sentence2Vec,
  which is actually a wrapper to Word2Vec. To obtain the vector of a
  sentence, I simply get the averaged vector sum of each word in the
  sentence.</p>
</blockquote>

<p>It certainly seems that, at least for practitioners, this simple averaging of the individual word vectors is far from unexpected. </p>

<p>An expected counter-argument here is that blog posts and SO answers are arguably not <em>that</em> credible sources; what about the <em>researchers</em> and the relevant <em>scientific literature</em>? Well, it turns out that this simple averaging is far from uncommon here, too:</p>

<p>From <a href="https://arxiv.org/abs/1405.4053" rel="noreferrer">Distributed Representations of Sentences and Documents</a> (Le &amp; Mikolov, Google, ICML 2014):</p>

<p><a href="https://i.stack.imgur.com/dstJK.png" rel="noreferrer"><img src="https://i.stack.imgur.com/dstJK.png" alt="enter image description here"></a></p>

<p>From <a href="http://www.aclweb.org/anthology/S17-2100" rel="noreferrer">NILC-USP at SemEval-2017 Task 4: A Multi-view Ensemble for Twitter Sentiment analysis</a> (SemEval 2017, section 2.1.2):</p>

<p><a href="https://i.stack.imgur.com/7MHAH.png" rel="noreferrer"><img src="https://i.stack.imgur.com/7MHAH.png" alt="enter image description here"></a></p>

<hr>

<p>It should be clear by now that the particular design choice in Spark ML is far from arbitrary, or even uncommon; I have blogged about what certainly seem as <em>absurd</em> design choices in Spark ML (see <a href="https://www.nodalpoint.com/spark-classification/" rel="noreferrer">Classification in Spark 2.0: “Input validation failed” and other wondrous tales</a>), but it seems that this is not such a case...</p>
Why does Spark's Word2Vec return a vector?
<p>Running the <a href="https://github.com/apache/spark/blob/master/examples/src/main/java/org/apache/spark/examples/ml/JavaWord2VecExample.java" rel="nofollow noreferrer">Spark's example for Word2Vec</a>, I realized that it takes in an array of string and gives out a vector. My question is, shouldn't it return a matrix instead of a vector? I was expecting one vector per input word. But it returns one vector period!</p>

<p>Or maybe it should have accepted string, instead of an array of strings (one word) as input. Then, yeah sure, it could return one vector as output. But accepting an array of strings and returning one single vector does not make sense to me.</p>

<p><strong>[UPDATE]</strong></p>

<p>Per @Shaido's request, here's the code with my minor change to print the schema for the output:</p>

<pre><code>public class JavaWord2VecExample {
    public static void main(String[] args) {
        SparkSession spark = SparkSession
                .builder()
                .appName("JavaWord2VecExample")
                .getOrCreate();

        // $example on$
        // Input data: Each row is a bag of words from a sentence or document.
        List&lt;Row&gt; data = Arrays.asList(
                RowFactory.create(Arrays.asList("Hi I heard about Spark".split(" "))),
                RowFactory.create(Arrays.asList("I wish Java could use case classes".split(" "))),
                RowFactory.create(Arrays.asList("Logistic regression models are neat".split(" ")))
        );
        StructType schema = new StructType(new StructField[]{
                new StructField("text", new ArrayType(DataTypes.StringType, true), false, Metadata.empty())
        });
        Dataset&lt;Row&gt; documentDF = spark.createDataFrame(data, schema);

        // Learn a mapping from words to Vectors.
        Word2Vec word2Vec = new Word2Vec()
                .setInputCol("text")
                .setOutputCol("result")
                .setVectorSize(7)
                .setMinCount(0);

        Word2VecModel model = word2Vec.fit(documentDF);
        Dataset&lt;Row&gt; result = model.transform(documentDF);

        for (Row row : result.collectAsList()) {
            List&lt;String&gt; text = row.getList(0);
            System.out.println("Schema: " + row.schema());
            Vector vector = (Vector) row.get(1);
            System.out.println("Text: " + text + " =&gt; \nVector: " + vector + "\n");
        }
        // $example off$

        spark.stop();
    }
}
</code></pre>

<p>And it prints:</p>

<pre><code>Schema: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))
Text: [Hi, I, heard, about, Spark] =&gt; 
Vector: [-0.0033279924420639875,-0.0024428479373455048,0.01406305879354477,0.030621735751628878,0.00792500376701355,0.02839711122214794,-0.02286271695047617]

Schema: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))
Text: [I, wish, Java, could, use, case, classes] =&gt; 
Vector: [-9.96453288410391E-4,-0.013741840076233658,0.013064394239336252,-0.01155538750546319,-0.010510949650779366,0.004538436819400106,-0.0036846946126648356]

Schema: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))
Text: [Logistic, regression, models, are, neat] =&gt; 
Vector: [0.012510885251685977,-0.014472834207117558,0.002779599279165268,0.0022389178164303304,0.012743516173213721,-0.02409198731184006,0.017409833287820222]
</code></pre>

<p>Please correct me if I'm wrong, but the input is an array of strings and the output is a single vector. And I was expecting each word to be mapped into a vector.</p>