Process N lists simultaneously by doing permutations
Not sure why you're making it so hard on yourself. Why not just go through each of the 3 queues individually?

For the first queue, just go through it and make a new Node for each element. Add it to your result list.

For the other 2 queues, check if the index is already in the result list. If it is, add it to that node, otherwise create a new node.



EDIT it seems my point wasn't clear, so let me show you the difference:

public Map&lt;String, List&lt;Tuple3&lt;Node, Node, Node&gt;&gt;&gt; transform2() {
    Map&lt;String, List&lt;Tuple3&lt;Node, Node, Node&gt;&gt;&gt; result = new LinkedHashMap&lt;&gt;(estimateSize() / 3);

    for (Node node : xpn) {
        if (!result.containsKey(node.getUniqueKey())) {
            result.put(node.getUniqueKey(), new LinkedList&lt;&gt;());
        }
        result.get(node.getUniqueKey()).add(new Tuple3&lt;Node, Node, Node&gt;(node, null, null));
    }

    for (Node node : tu) {
        if (!result.containsKey(node.getUniqueKey())) {
            result.put(node.getUniqueKey(), new LinkedList&lt;&gt;());
        }
        List&lt;Tuple3&lt;Node, Node, Node&gt;&gt; tuples = result.get(node.getUniqueKey());
        boolean needNew = true;
        for (Tuple3&lt;Node, Node, Node&gt; tuple : tuples) {
            if (tuple._2() == null) {
                tuple.update2(node);
                needNew = false;
                break;
            }
        }
        if (needNew) {
            tuples.add(new Tuple3&lt;&gt;(null, node, null));
        }
    }

    for (Node node : efx) {
        if (!result.containsKey(node.getUniqueKey())) {
            result.put(node.getUniqueKey(), new LinkedList&lt;&gt;());
        }
        List&lt;Tuple3&lt;Node, Node, Node&gt;&gt; tuples = result.get(node.getUniqueKey());
        boolean needNew = true;
        for (Tuple3&lt;Node, Node, Node&gt; tuple : tuples) {
            if (tuple._3() == null) {
                tuple.update3(node);
                needNew = false;
                break;
            }
        }
        if (needNew) {
            tuples.add(new Tuple3&lt;&gt;(null, null, node));
        }
    }
    return result;
}


I personally find this a lot easier to understand than all your indirections and switches.

If you really don't want to have one big method you can also split it up like this:

public Map&lt;String, List&lt;Tuple3&lt;Node, Node, Node&gt;&gt;&gt; transform() {
    Map&lt;String, List&lt;Tuple3&lt;Node, Node, Node&gt;&gt;&gt; result = new LinkedHashMap&lt;&gt;(estimateSize() / 3);

    for (Node node : xpn) {
        Tuple3&lt;Node, Node, Node&gt; tuple = getTupleToModify(result, node.getUniqueKey(), (n -&gt; null == n._1()));
        tuple.update1(node);
    }

    for (Node node : tu) {
        Tuple3&lt;Node, Node, Node&gt; tuple = getTupleToModify(result, node.getUniqueKey(), (n -&gt; null == n._2()));
        tuple.update2(node);
    }

    for (Node node : efx) {
        Tuple3&lt;Node, Node, Node&gt; tuple = getTupleToModify(result, node.getUniqueKey(), (n -&gt; null == n._3()));
        tuple.update3(node);
    }
    return result;
}

private Tuple3&lt;Node, Node, Node&gt; getTupleToModify(
        Map&lt;String, List&lt;Tuple3&lt;Node, Node, Node&gt;&gt;&gt; currentTuples,
        String key, Function&lt;Tuple3&lt;Node, Node, Node&gt;,
        Boolean&gt; filter) {

    if (!currentTuples.containsKey(key)) {
        currentTuples.put(key, new LinkedList&lt;&gt;());
    }

    List&lt;Tuple3&lt;Node, Node, Node&gt;&gt; list = currentTuples.get(key);
    for (Tuple3&lt;Node, Node, Node&gt; tuple : list) {
        if (filter.apply(tuple)) {
            return tuple;
        }
    }
    Tuple3&lt;Node, Node, Node&gt; result = new Tuple3&lt;&gt;(null, null, null);
    list.add(result);
    return result;
}