Steve W
Steve W

Reputation: 1128

Replace nested for loops with parallel stream - Java

I'm working on improving the speed of a program where performance is critical. Currently it fails to process large data sets. There are many nested for loops and so I thought it would be worth trying parallel streams. I have access to a high performance cluster so potentially have many cores available. I have the method below:

public MinSpecSetFamily getMinDomSpecSets() {
        MinSpecSetFamily result = new MinSpecSetFamily();
        ResourceType minRT = this.getFirstEssentialResourceType();
        if (minRT == null || minRT.noSpecies()) {
            System.out.println("Problem in getMinDomSpecSets()");
        }
        for (Species spec : minRT.specList) {
            SpecTree minTree = this.getMinimalConstSpecTreeRootedAt(spec);
            ArrayList<SpecTreeNode> leafList = minTree.getLeaves();
            for (SpecTreeNode leaf : leafList) {
                ArrayList<Species> sp = leaf.getAncestors();
                SpecSet tmpSet = new SpecSet(sp);
                result.addSpecSet(tmpSet);
            }
        }
        return result;
    }

I understand that I can turn a nested for loop into a parallel stream with something like:

minRT.specList.parallelStream().flatMap(leaf -> leaflist.parallelStream())

However, I cannot find examples showing how to deal with the actions inside each for loop and I'm not at all confident about how this is supposed to work. I'd really appreciate some assistance and explanation of how to convert this method so that I can translate the solution to other methods in the program too. Thanks.

Upvotes: 2

Views: 1455

Answers (1)

Eran
Eran

Reputation: 393956

Here's one way of doing it (hopefully I have no typos):

MinSpecSetFamily result =
    minRT.specList
         .parallelStream()
         .flatMap(spec -> getMinimalConstSpecTreeRootedAt(spec).getLeaves().stream())
         .map(leaf -> new SpecSet(leaf.getAncestors()))
         .reduce(new MinSpecSetFamily (),
                 (fam,set)-> {
                     fam.addSpecSet(set);
                     return fam;
                 },
                 (f1, f2) -> new MinSpecSetFamily(f1, f2));

EDIT: Following Holger's comment, you should use collect instead of reduce:

MinSpecSetFamily result =
    minRT.specList
         .parallelStream()
         .flatMap(spec -> getMinimalConstSpecTreeRootedAt(spec).getLeaves().stream())
         .map(leaf -> new SpecSet(leaf.getAncestors()))
         .collect(MinSpecSetFamily::new,MinSpecSetFamily::addSpecSet,MinSpecSetFamily::add);

Upvotes: 2

Related Questions