Actually, there is very little in it and is probably dependent on hardware and other factors.
The setLength() method simply alters the count and overwrites the unwanted value in the array with a zero byte.
The deleteCharAt() performs an array copy internally, before altering the count. That sounds dramatic, but the array being copied is actually zero-length because you're removing the last character.
I would recommend going for setLength() as it is shorter to type and I think makes it clearer what you are doing. If performance is an issue and, on measuring, you find this is the bottleneck for you, then perhaps you could consider a different algorithm that doesn't require changing the size (as per JB Nizet's answer).
How you do it properly is to conditionally prepend the comma:
for (int i = 0; i < nums.length; i++) {
if (i > 0)
sb.append(',');
sb.append(nums[i]);
}
Then you don't need to worry about removing the last character, because it's already correct.
The third part of the for statement is the instruction that should increment or decrement your index.
There, it is always 4.
To be clearer :
1st iteration : i = 2 => you remove the 'd', your string is now "I on't know this"
2nd iteration : i = 4 => you remove the ''', your string is now "I ont know this"
3rd iteration : i = 4 => you remove the 't', your string is now "I on know this"
4th iteration : i = 4 => you remove the ' ', your string is now "I onknow this"
...
If you want to remove characters from a String I recommend you to use Regex. This is an example to replace with empty strings the characters that you need to remove:
public static String cleanWhitPattern(String sample, String , String regex) {
if (sample != null && regex != null) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sample);
if (matcher.find()) {
return matcher.replaceAll("");
}
return sample;
}
return null;
}
Now, you simply call this method with your required pattern:
System.out.print(cleanWithPattern("I don't know this", "o*"));
And your output should be this:
I dn't knw this
For String, StringBuffer, and StringBuilder, charAt() is a constant-time operation.
For StringBuffer and StringBuilder, deleteCharAt() is a linear-time operation.
StringBuffer and StringBuilder have very similar performance characteristics. The primary difference is that the former is synchronized (so is thread-safe) while the latter is not.
Let us just look at the corresponding actual java implementation(only relevant code) for each of these methods in turn. That itself will answer about their efficiency.
String.charAt :
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
As we can see, it is just a single array access which is a constant time operation.
StringBuffer.charAt :
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
Again, single array access, so a constant time operation.
StringBuilder.charAt :
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
Again, single array access, so a constant time operation. Even though all these three methods look same, there are some minor differences. For example, only StringBuffer.charAt method is synchronized but not other methods. Similarly if check is slightly different for String.charAt (guess why?). Closer look at these method implementations itself give us other minor differences among them.
Now, let us look at deleteCharAt implementations.
String does not have deleteCharAt method. The reason might be it is an immutable object. So exposing an API which explicitly indicates that this method modifies the object is not probably a good idea.
Both StringBuffer and StringBuilder are subclasses of AbstractStringBuilder. The deleteCharAt method of these two classes is delegating the implementation to its parent class itself.
StringBuffer.deleteCharAt :
public synchronized StringBuffer deleteCharAt(int index) {
super.deleteCharAt(index);
return this;
}
StringBuilder.deleteCharAt :
public StringBuilder deleteCharAt(int index) {
super.deleteCharAt(index);
return this;
}
AbstractStringBuilder.deleteCharAt :
public AbstractStringBuilder deleteCharAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
System.arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
A closer look at AbstractStringBuilder.deleteCharAt method reveals that it is actually calling System.arraycopy. This can be O(N) in worst case. So deleteChatAt method is O(N) time complexity.