ArrayStringBuilder makes StringBuilder acts as an array
String concat is something that we need to do a lot when creating SQLs but there is a problem by using string-plus-string concatenation (“string”+”"string”): Every couple of quotations java will create and alocate one String class, this can be a trigger for memory problems.
The orientation (at Celepar) is to use StringBuffer that is faster than simple concat. Searching the web i found that StringBuilder is a bit faster than StringBuffer.
Now let me go to the point, i needed to make an join and use a separator at a group of strings, but memory was something i was worried, then i tried to simulate an array over StringBuilder, the result was the following class.
p.s: I really doen’t feel that there aren’t a better and faster way to do this, but i didn’t found anything at this time;
package com.br.webcentro.utils;
import java.util.Arrays;
/**
* This class works using the java.lang.StringBuilder,
* but this simulates an array to implement a joinable splitable string
*
* may be better extend the class AbstractStringBuilder but for now it will only work using it;
*
* feel free to post implementations
*
* If you have some advice please contact me at webcentro(at)gmail.com
* @author alandanielweiss
* @since 2010-01-22
*/
public class ArrayStringBuilder implements java.io.Serializable{
private StringBuilder builder;
private boolean isMultiEnabled = false;
private boolean isEmptyAllowed = true;
private int start[];
private int len[];
private int counter=0;
private int totalLen=0;
private static final long serialVersionUID = -2443226579329551214L;
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public ArrayStringBuilder() {
this.builder = new StringBuilder();
this.start = new int[16];
this.len = new int[16];
}
/**
* Sets the initial StringBuilder capacity
* @param capacity
*/
public ArrayStringBuilder(int capacity) {
this.builder = new StringBuilder(capacity);
this.start = new int[capacity];
this.len = new int[capacity];
}
/**
* Create class and append string
* @param string
*/
public ArrayStringBuilder(String string) {
this();
this.add(string);
}
/**
* Create class and the the StringBuilder
* @param string
*/
public ArrayStringBuilder(StringBuilder builder) {
this.start = new int[16];
this.len = new int[16];
this.counter = 1;
this.start[0] = 0;
this.len[0] = builder.toString().length();
this.totalLen = this.len[0];
this.builder = builder;
}
/**
* Append a string
* @param str
* @return
*/
public ArrayStringBuilder add(String str){
if (str == null)
str = "null";
int len = str.length();
if (len == 0 && !isEmptyAllowed)
return this;
//multi-line don't increment counter
if(!this.isMultiEnabled)
this.counter ++;
if (this.counter > start.length)
expandCapacity(this.counter);
if(!this.isMultiEnabled)
this.start[this.counter-1] = this.totalLen;
if(this.isMultiEnabled)
len +=this.len[this.counter-1];
this.len[this.counter-1] = len;
this.totalLen += str.length();
this.builder.append(str);
return this;
}
/**
* start multiline array
* when done use the method end()
* @return
*/
public ArrayStringBuilder start(String str){
this.isMultiEnabled = false;
this.add(str);
this.isMultiEnabled = true;
return this;
}
/**
* finish multiline array
* @return
*/
public ArrayStringBuilder finish(String str){
this.add(str);
this.isMultiEnabled = false;
return this;
}
void expandCapacity(int minimumCapacity) {
int newCapacity = (start.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
this.start = Arrays.copyOf(this.start, newCapacity);
this.len = Arrays.copyOf(this.len, newCapacity);
}
/**
* Joins the StringBuilder using the passed separator
* @param separator
* @return
*/
public String join(String separator){
StringBuilder str = new StringBuilder();
for (int idx=0; idx<this.counter;idx++){
str.append(this.builder.substring(this.start[idx], this.start[idx]+this.len[idx]));
if(idx+1<this.counter)
str.append(separator);
}
return str.toString();
}
public String[] toArray(){
String[] str = new String[this.counter];
for (int idx=0; idx<this.counter;idx++){
str[idx] = this.builder.substring(this.start[idx], this.start[idx]+this.len[idx]);
}
return str;
}
/**
* To string...
* @return String
*/
public String toString() {
return this.builder.toString();
}
/**
* Creates a StringBuilder with the actual object values
* @return builder:StringBuilder
*/
public StringBuilder getStringBuilder(){
return this.builder;
}
/**
* when true every time you use add/start/finish with an empty string it will add a new array
* if false the command add/start/finish empty has no effect
*/
public void setEmptyAllowed(boolean isMultiEnabled){
this.isMultiEnabled = isMultiEnabled;
}
public static void main(String[] args) {
//Sample 1
StringBuilder strb = new StringBuilder();
strb.append("to be");
ArrayStringBuilder arrb = new ArrayStringBuilder(strb);
arrb.start(" or ");
arrb.add("not ");
arrb.add("to ");
arrb.finish("be");
ArrayStringBuilder arrb2 = new ArrayStringBuilder(arrb.join(","));
System.out.println(arrb2.add(": that's").add("the").add("question").join(" "));
//Sample 2
ArrayStringBuilder fields = new ArrayStringBuilder();
fields.add("id");
if(1==1)
fields.add("name");
if(1==2)
fields.add("profession");
StringBuilder sql = new StringBuilder();
sql.append("select ").append(fields.join(" , ")).append(" from table ");
System.out.println(sql.toString());
}
}
A good comparision between StringBuilder and StringBuffer can be found at: StringBuilder vs StringBuffer vs String.concat – done right
Please feel free to send comments, to improve this class.
Nenhum trackbacks ainda.