Questo invece scansiona la matrice "per colonne". Funzionante a condizione che: a) ci sia almeno una riga; b) l'array sia "rettangolare" (e non "jagged")
String[][] matrice = {
{ "aaa", "bbb", "ccc" },
{ "ddd", "eee", "fff" },
{ "ggg", "hhh", "iii" },
};
String resultString = IntStream.range(0, matrice[0].length)
.boxed()
.flatMap(indiceColonna -> Arrays.stream(matrice)
.map(subarr -> subarr[indiceColonna]))
.collect(Collectors.joining(","));
resultString contiene "aaa,ddd,ggg,bbb,eee,hhh,ccc,fff,iii"
Ovvero: prima tutti i dati della colonna 0, poi tutti i dati della colonna 1, ecc...
Probabilmente (sicuramente) non è il massimo e si può fare di meglio ma ... in questo momento non ho tempo di approfondire.
Ripeto: questi sono sempre "esempi" da cui puoi prendere spunto.