Merging key-value sets as specified by a command private void merge(ArrayList&lt;String&gt; operations, ArrayList&lt;LinkedHashSet&lt;String&gt;&gt; setOfStrings) {
        String toMerge = operations.get(1);
        String fromMerge = operations.get(2);
        boolean enteredFirstToMerge = false;
        boolean enteredFirstForMerge = false;
        // references that points one on toMerge and the other on fromMerge
        LinkedHashSet&lt;String&gt; toMergeAndAfterDelete = null;
        LinkedHashSet&lt;String&gt; addOnFromMerge = null;
        for (LinkedHashSet&lt;String&gt; subSet : setOfStrings) {
        if (subSet.contains(toMerge) &amp;&amp; subSet.contains(fromMerge))
            break;
        else {
            if (subSet.contains(toMerge) &amp;&amp; !enteredFirstToMerge) {
            toMergeAndAfterDelete = subSet;
            enteredFirstToMerge = true;
            }
            if (subSet.contains(fromMerge) &amp;&amp; !enteredFirstForMerge) {
            addOnFromMerge = subSet;
            enteredFirstForMerge = true;
            }
            if ((enteredFirstForMerge &amp;&amp; enteredFirstToMerge)) {
            break;
            }
          }
        }
        /***********************************************/
        //outside Loop i call the remove on the arraylist
        //that are very expensive    
        /*************************************************/   
        if (enteredFirstForMerge &amp;&amp; enteredFirstToMerge) {
        // first i delete from the array the linkedHashSet toMerge and
        // fromMerge and after i add a 
        // new linkedHashSet with the subSets merged
        setOfStrings.remove(toMergeAndAfterDelete);  
        setOfStrings.remove(addToMergeOnFromMerge); 
        addOnFromMerge.addAll(toMergeAndAfterDelete);
        setOfStrings.add(addOnFromMerge);
        }
}


This function takes as parameter an arrayList of operations, and an ArrayList&lt;LinkedHashSet&lt;String&gt;&gt;:

For the arrayList of operations, I always get a specific position, so I don't iterate.    It is always \$O(1)\$.

For example, if I have as operation move foo bar, I have to do these steps:


First of all, I have to find where are located foo and bar:


Inside setOfStrings, I can have this situation:

    position x : {bar tree hotel}
    ...
    position y : {foo lemon coffee} 




When I find them, I have to  concat the foo string into bar string  in this way:

            position x : {bar tree hotel foo lemon coffee}
            ...
            position y : {} 


How can I improve the efficiency of this function?
Abstract as much as possible over type: List instead of ArrayList.   
Use OO where appropriate: List&lt;String&gt; operations should clearly be some
class MoveOperation(String to, String from).
It's not clear why you are using LinkedHashSet instead of List.
The algorithm is ill-defined: what happens if there are numerous
foo's or bar's.


I implemented something below, but it is in functional style, so it might be hard to read.  There are three implicit loops: two for the filters and one for the map.  You might also notice that I never modify a collection, but always create a new one.  Again, this is the functional style.  In your algorithm, you can actually shoot yourself in the foot if you modify some collections at the wrong moment.

private List&lt;List&lt;String&gt;&gt; merge2(List&lt;String&gt; operations, List&lt;List&lt;String&gt;&gt; listOfSentences) {
    Stream&lt;List&lt;String&gt;&gt; sentencesWithTo = listOfSentences.stream()
                                           .filter(sentence -&gt; sentence.contains(toMerge));
    Stream&lt;List&lt;String&gt;&gt; sentencesWithFrom = listOfSentences.stream()
                                             .filter(sentence -&gt; sentence.contains(fromMerge));

    long nTo = sentencesWithTo.count();
    long nFrom = sentencesWithFrom.count();

    if (nTo == 0  || nFrom == 0) {
        return listOfSentences;
    } else if (nTo &gt; 1 || nFrom &gt; 1) {
        // what to do here??
    } else {
        List&lt;String&gt; sentenceTo = sentencesWithTo.collect(Collectors.toList()).get(0); // should only be one element ?
        List&lt;String&gt; sentenceFrom = sentencesWithFrom.collect(Collectors.toList()).get(0); // should only be one element ?
        Stream&lt;List&lt;String&gt;&gt; updatedSentences = listOfSentences.stream().map(sentence -&gt; {
            if (sentence.equals(sentenceTo))
                return Stream.concat(sentenceTo.stream(), sentenceFrom.stream()).collect(Collectors.toList());
            else if (sentence.equals(sentenceFrom))
                return new ArrayList&lt;&gt;();
            else 
                return sentence;
        });
        return updatedSentences.collect(Collectors.toList());
    }
}