Supponendo di poter dividere in modo efficiente i file in blocchi (ad esempio, gruppi di linee), puoi provare ad associare alcuni blocchi a ciascun thread e creare una hashmap per ciascuno dei tuoi thread. Non appena sono terminati due thread, puoi unire le loro hashmap in una nuova nuova hashmap (l'hashmap non è altro che una monade), e procedere fino a ottenere una singola hashmap finale contando le parole per l'intero file.
Devi sintonizzare alcuni parametri per trovare il compromesso più interessante tra granularità fine ed efficienza: numero di thread, numero di blocchi, ecc.
Un'implementazione probabilmente subottimale ma semplice sarebbe quella di aspettare che tutte le hashmaps siano state create prima di unirle tutte nello stesso momento. Un tentativo non controllato in Java 8:
Function<String, Map<String, Long>> countWords = (block) -> {
Map<String, Long> ret = new HashMap<String, Long>();
for(String word : block.split(" ")){
ret.merge(word, 1, (a,b) -> a+b);
}
return ret;
};
BinaryOperator<Map<String, Long>> combine = (m1, m2) -> {
Map<String, Long> m3 = new HashMap<>(m1);
m2.forEach((k, v) -> m3.merge(k, v, (a,b) -> a+b);
return m3;
};
Stream<String> blocks = file.getLineBlocks().parallelStream();
Stream<Map<String, Long>> counts = blocks.map(block -> countWords(blocks));
Map<String, Long> count = counts.reduce(new HashMap<String, Long>(), combine);