简体   繁体   中英

How to join two nullable sets in Java

I have two maps that have a String as the key, and Set as its value. These two maps can share the same keys. I'm trying to merge the two Set values together if the two maps have the same key. The problem is, the second map might be null, and since not all keys are shared between the two maps, the Sets might also be null. I've come up with a couple options, but they all look pretty messy. Was wondering if anyone had a more efficient/prettier way of doing it. This is what I have so far:

Set<String> mergedSet = (firstMap.containsKey(commonKey)) ? firstMap.get(commonKey) : new HashSet<String>();

mergedSet.addAll(secondMap != null && secondMap.containsKey(commonKey) ? secondMap.get(commonKey) : new HashSet<String>());

I would use Guava's HashMultimap instead of a Map<String, Set<String>> . It has the following advantages:

  • shortcut methods to add multiple values for a given key, without caring if a Set already exists for this key of not
  • always returns a non-null Set when get(key) is called, even if nothing was ever stored for this key.

So your code would become:

Set<String> mergedSet = Sets.union(firstMultimap.get(commonKey),
                                   secondMultimap.get(commonKey));

The set would simply be a view over the two sets, which avoids copying every element. But if you want a copy, then do

Set<String> mergedSet = Sets.newHashSet(Sets.union(firstMultimap.get(commonKey),
                                                   secondMultimap.get(commonKey)));

If you don't want to go with an external library, then your code is pretty much OK. I would use Collections.singletonSet() for the second fallback set though, to avoid an unnecessary empty set creation. And be careful: your code modified the first set. It doesn't make a copy of it. So in the end, every set of the first map is in fact a merged set.

To some extent, this is more an issue of style, but there are a few things to comment on. First, the containsKey and get methods have equal cost, so it's more efficient to call get and check for a null return value. Second, in your example, you set the mergedSet to firstMap.get(commonKey) which means you're modifying the set in firstMap and it will be the merged set. I'm guessing that you don't want to modify the sets in firstMap . I would suggest using the longer:

Set<String> mergedSet = new HashSet<String>();

Set<String> firstSet = firstMap.get(commonKey);
if (firstSet != null)
{
    mergedSet.addAll(firstSet);
}

if (secondMap != null)
{
    Set<String> secondSet = secondMap.get(commonKey);
    if (secondSet != null)
    {
        mergedSet.addAll(secondSet);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM