Search This Blog

Wednesday, October 10, 2012

How To Print A List of Comma-Seperated Values Nicely and Remove the Last (',') Comma Value


I recently wanted to take a list of Strings (i.e. List<String> list) and print that out with each value seperated by a comma and inside a set of brackets. The idea is I'd have something like this at the end:

    (String1,String2,String3)

However my first cut attempt at a loop was creating the list above but with a superfluous ',' at the end like so:

    (String1,Strng2,String3,)

Which was based on this code (where list was my List<String>):>

    StringBuilder sb = new StringBuilder("(");
    for (String string : list) {
        sb.append(string);
        sb.append(",");
    }
    sb.append(")");     //close the end bracket

So I decided to find a way or three to do this more nicely. What follows is 3 different ways of implementing this to get the correct implementation using a TestNG test case for testing. Each implementation, which achievs the same thing in each case is in one of the getVersion#() methods. Feel free to use any one of these 3 possible, simple implementations of the same thing to get the nicely comma seperated list with the end comma nicely removed.

  @Test
  public void testClass() {
    //Create a list of strings to be used in each test case
    List<String> list = new ArrayList<String>(Arrays.asList("String1", "String2", "String3"));
   
    //setup the expected result string based on the list above
    final String EXPECTED_RESULT = "(String1,String2,String3)";
   
    StringBuffer sb = getVersion1(list);
    System.out.println("1st string test:" + sb.toString());
    Assert.assertEquals(sb.toString(), EXPECTED_RESULT);
   
    sb = getVersion2(list);

    System.out.println("2nd string test:" + sb2.toString());
    Assert.assertEquals(sb2.toString(), EXPECTED_RESULT);
   
    sb = getVersion3(list);

    System.out.println("3rd string test:" + sb3.toString());
    Assert.assertEquals(sb3.toString(), EXPECTED_RESULT);
  }


  /**
   * This method puts the comma first so that we have the extra comma at the
   * start and then uses the deleteCharAt() method to delete the 1st ','
   */
  private StringBuffer getVersion1(List list) {
    //begin 1st case: ',' at start and deleteCharAt(0 or 1)
   
StringBuffer sb = new StringBuffer("(");
    for (String string : list) {
      sb.append(",");
      sb.append(string);
    }
    sb.deleteCharAt(1); //remove 1st ',' symbol (or if extra char's before bracket increse number)
    sb.append(")");     //close the end bracket


    return sb;
  }

  /**
   * This method puts the comma at the end in the common wayand then uses 
   * the deleteCharAt() method along with the length of the StringBuffer
   * to delete the last ',' symbol from the list before appending the ).
   */
  private StringBuffer getVersion2(List list) {
    //begin 2nd case: ',' at end and deleteCharAt(last character)
   
StringBuffer sb2 = new StringBuffer("(");
    for (String string : list) {
      sb2.append(string);
      sb2.append(",");
    }
    sb2.deleteCharAt(sb2.length() - 1); //remove the 1st ',' symbol
    sb2.append(")");     //close the end bracket


    return sb;
  }

  /**   
   * The final method of implementing this places the excess ',' at the end like 
   * is standard but then does the delete and append(")") steps in a single step
   * via the replace() call which replaces the lat ',' with the ')' bracket.
   */ 
  private StringBuffer getVersion3(List list) {
    //begin 3rd case:  ',' at end and replace the last character with the bracket achieving both at the same time
    StringBuffer sb3 = new
StringBuffer("(");
    for (String string : list) {
      sb3.append(string);
      sb3.append(",");
    }
    sb3.replace(sb3.length() - 1, sb3.length(), ")");


So there ya go, 3 different methods all very similar, to implement a comma-seperated list without the pesky comma at the end of the list and implemented in a TestNG test with Assertions to prove it worked as expected.  Note: In all 3 cases the performance is pretty much the same. When looking at the deleteCharAt() followed by an append() as compared to a replace() call they are pretty much identical in terms of what they are going to need to do. Although the internals vary the key performance hit is the call to the System.arrayCopy() which is where the time is spent. Either way there are 3 calls to System.arrayCopy() to perform this work, which reeally should be unsuprsing since in both cases we are doing pretty much the same thing just reducing the number of lines required to implement it. My choice is the 1st option as it looks the neatest (even if it does take one line more than the replace() method).

No comments:

Post a Comment