Is there a better way to combine two string sets in java?

JavaSet

Java Problem Overview


I need to combine two string sets while filtering out redundant information, this is the solution I came up with, is there a better way that anyone can suggest? Perhaps something built in that I overlooked? Didn't have any luck with google.

Set<String> oldStringSet = getOldStringSet();
Set<String> newStringSet = getNewStringSet();
        
for(String currentString : oldStringSet)
{
    if (!newStringSet.contains(currentString))
    {
        newStringSet.add(currentString);
    }
}

Java Solutions


Solution 1 - Java

Since a Set does not contain duplicate entries, you can therefore combine the two by:

newStringSet.addAll(oldStringSet);

It does not matter if you add things twice, the set will only contain the element once... e.g it's no need to check using contains method.

Solution 2 - Java

You can do it using this one-liner

Set<String> combined = Stream.concat(newStringSet.stream(), oldStringSet.stream())
        .collect(Collectors.toSet());

With a static import it looks even nicer

Set<String> combined = concat(newStringSet.stream(), oldStringSet.stream())
        .collect(toSet());

Another way is to use flatMap method:

Set<String> combined = Stream.of(newStringSet, oldStringSet).flatMap(Set::stream)
        .collect(toSet());

Also any collection could easily be combined with a single element

Set<String> combined = concat(newStringSet.stream(), Stream.of(singleValue))
        .collect(toSet());

Solution 3 - Java

The same with Guava:

Set<String> combinedSet = Sets.union(oldStringSet, newStringSet)

Solution 4 - Java

From the definition Set contain only unique elements.

Set<String> distinct = new HashSet<String>(); 
 distinct.addAll(oldStringSet);
 distinct.addAll(newStringSet);

To enhance your code you may create a generic method for that

public static <T> Set<T> distinct(Collection<T>... lists) {
	Set<T> distinct = new HashSet<T>();
	
	for(Collection<T> list : lists) {
		distinct.addAll(list);
	}
	return distinct;
}

Solution 5 - Java

If you are using Guava you can also use a builder to get more flexibility:

ImmutableSet.<String>builder().addAll(someSet)
                              .addAll(anotherSet)
                              .add("A single string")
                              .build();

Solution 6 - Java

If you are using the Apache Common, use SetUtils class from org.apache.commons.collections4.SetUtils;

SetUtils.union(setA, setB);

Solution 7 - Java

Just use newStringSet.addAll(oldStringSet). No need to check for duplicates as the Set implementation does this already.

Solution 8 - Java

http://docs.oracle.com/javase/7/docs/api/java/util/Set.html#addAll(java.util.Collection)

Since sets can't have duplicates, just adding all the elements of one to the other generates the correct union of the two.

Solution 9 - Java

 newStringSet.addAll(oldStringSet);

This will produce Union of s1 and s2

Solution 10 - Java

Set.addAll()

Adds all of the elements in the specified collection to this set if they're not already present (optional operation). If the specified collection is also a set, the addAll operation effectively modifies this set so that its value is the union of the two sets

newStringSet.addAll(oldStringSet)

Solution 11 - Java

Use boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this set if they're not already present (optional operation). If the specified collection is also a set, the addAll operation effectively modifies this set so that its value is the union of the two sets. The behavior of this operation is undefined if the specified collection is modified while the operation is in progress.

newStringSet.addAll(oldStringSet)

Solution 12 - Java

If you care about performance, and if you don't need to keep your two sets and one of them can be huge, I would suggest to check which set is the largest and add the elements from the smallest.

Set<String> newStringSet = getNewStringSet();
Set<String> oldStringSet = getOldStringSet();

Set<String> myResult;
if(oldStringSet.size() > newStringSet.size()){
    oldStringSet.addAll(newStringSet);
    myResult = oldStringSet;
} else{
    newStringSet.addAll(oldStringSet);
    myResult = newStringSet;
}

In this way, if your new set has 10 elements and your old set has 100 000, you only do 10 operations instead of 100 000.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFooBarView Question on Stackoverflow
Solution 1 - JavadacweView Answer on Stackoverflow
Solution 2 - JavaytterrrView Answer on Stackoverflow
Solution 3 - JavaAlexander PrankoView Answer on Stackoverflow
Solution 4 - JavaDamian Leszczyński - VashView Answer on Stackoverflow
Solution 5 - JavaLeonardo BernardesView Answer on Stackoverflow
Solution 6 - JavaVinit SolankiView Answer on Stackoverflow
Solution 7 - JavatobiasbayerView Answer on Stackoverflow
Solution 8 - JavaViruzzoView Answer on Stackoverflow
Solution 9 - JavaKushanView Answer on Stackoverflow
Solution 10 - JavaUmNyobeView Answer on Stackoverflow
Solution 11 - JavaSumit SinghView Answer on Stackoverflow
Solution 12 - JavaRicolaView Answer on Stackoverflow