views:

211

answers:

5

I have a method in Java that concatenates 2 Strings. It currently works correctly, but I think it can be written better.

public static String concat(String str1, String str2) {
  String rVal = null;
  if (str1 != null || str2 != null) {
    rVal = "";
    if (str1 != null) {
      rVal += str1;
    }
    if (str2 != null) {
      rVal += str2;
    }      
  }    
  return rVal;
}

Here are some of the requirements:

  1. If both str1 and str2 are null, the method returns null
  2. If either str1 or str2 is null, it will just return the not null String
  3. If str1 and str2 are not null, it will concatenate them
  4. It never adds "null" to the result

Can anyone do this with less code?

+8  A: 

Sure:

public static String concat(String str1, String str2) {
  return str1 == null ? str2
      : str2 == null ? str1
      : str1 + str2;
}

Note that this takes care of the "both null" case in the first condition: if str1 is null, then you either want to return null (if str2 is null) or str2 (if str2 is not null) - both of which are handled by just returning str2.

Jon Skeet
Nested conditional operators? Seriously?
Michael Borgwardt
Some can read it, some cannot. It's indeed more confusing for starters. I would rather have put them in a single line with parentheses. Something like `return (str1 == null) ? str2 : ((str2 == null) ? str1 : (str1 + str2));`
BalusC
@Michael: Absolutely - I find it a very useful pattern when you want to test multiple conditions with a preference.
Jon Skeet
@BalusC: I find the parentheses add confusion whereas the line breaks show the logical structure more clearly. It's a personal preference thing though.
Jon Skeet
*urks* Please add the version without conditional operator for completeness and beauty. Sometimes more code is less confusion!
Hardcoded
@Jon Skeet: true, it's personal. But I've experienced that starters understand it better when you use parentheses to separate conditions and expressions. After a year or five, they will start write and understand it without parentheses ;) As the OP is already asking this relatively simple question, I bet that he falls in the category "starter".
BalusC
@Jon: Useful yes, but utterly baffling when you're not used to it, and IMO not useful enough to inflict it on unsuspecting newbies.
Michael Borgwardt
Thanks Jon and Michael. I prefer Jon's method because I don't mind conditionals. I also prefer one return statement per method.
GooF
+9  A: 

Using only plain if clauses:

public static String concat(String str1, String str2) {
    if(str1==null) return str2;
    if(str2==null) return str1;
    return str1 + str2;
}

Or, if you have a deep and passionate love for parentheses:

public static String concat(String str1, String str2) {
    if(str1==null)
    { 
        return str2;
    }
    if(str2==null) 
    {
        return str1;
    }
    return str1 + str2;
}
Michael Borgwardt
You don't like nested conditionals - I don't like `if` statements without braces :)
Jon Skeet
@Jon had those at first, but compactness IMO is better in such a simple case.
Michael Borgwardt
Less code is more readable
Steve Kuo
A: 
import org.apache.commons.lang.StringUtils;

StringUtils.join([str1, str2]);

Joins the elements of the provided array into a single String containing the provided list of elements.

No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings.

 StringUtils.join(null)            = null
 StringUtils.join([])              = ""
 StringUtils.join([null])          = ""
 StringUtils.join(["a", "b", "c"]) = "abc"
 StringUtils.join([null, "", "a"]) = "a"
Nishu
@Nishu This is close, but a simple null check is needed in case both str1 and str2 are both null.
GooF
A: 

Everyone seems to have missed condition 1 where if both strings are null it returns null. The simplest version to read (IMO) then becomes:

public static String concat(String str1, String str2) {  
    if(str1==null && str2==null) return null;  
    if(str1==null) return str2;  
    if(str2==null) return str1;  
    return str1 + str2;  
}
Striker
I take that back...the first answer by Jon did...
Striker
Both Jon and Michael's solutions would return null on the first condition (returning the other String, which is null) if both strings are null. Yours just adds an extra unnecessary test condition.
Kavon Farvardin
A: 
public class ConcatTest extends TestCase {

    // 1. If both str1 and str2 are null, the method returns null
    public void testBothNull() throws Exception {
        assertNull(concat(null, null));
    }

    // 2. If either str1 or str2 is null, it will just return the not null
    // String
    public void testOneNull() throws Exception {
        assertEquals("a", concat(null, "a"));
        assertEquals("b", concat("b", null));
    }

    // 3. If str1 and str2 are not null, it will concatenate them
    public void testNonNull() throws Exception {
        assertEquals("ab", concat("a", "b"));
    }

    // 4. It never adds "null" to the result (not really testable)

    public static String concat(String a, String b) {
        if (a == null && b == null)
            return null;
        return denulled(a) + denulled(b);
    }

    private static String denulled(String s) {
        return s == null ? "" : s;
    }

}
Carl Manaster