我有这个循环,它将布尔的LinkedList拆分为8位,并返回缓冲区中每个字节的ASCII值。该函数返回字符串缓冲区。
如果LinkedList的大小很大,这段代码非常慢。我尝试用简单的循环来改变Iterator
,但它仍然很慢。
这个算法怎么能真快?也许有多线程?
注意: linkList的大小并不总是可以被8整除。
public String toString(){
String buffer = "";
String output = "";
LinkedList<Boolean> bits = this.bits;
for(Iterator it = this.bits.iterator(); it.hasNext();){
if(buffer.length() >= 8){
output += (char)Integer.parseInt(buffer, 2);
buffer = "";
}
buffer += ((Boolean)it.next() == false) ? "0" : "1";
}
if(buffer != "")
output += (char)Integer.parseInt(buffer, 2);
return output;
}
答案 0 :(得分:8)
这些建议将为您提供足够的性能,同时保持代码简单易读。首先使用这些更改进行测试,如果不符合您的性能要求,请慢慢引入其他答案中建议的优化技术
BitSet
代替LinkedList<Boolean>
StringBuilder output;
代替String output;
StringBuilder buffer;
代替String buffer;
Integer.valueOf()
代替Integer.parseInt
。 valueOf
使用缓存来估算低于128的值。答案 1 :(得分:7)
使用StringBuilder
初始化预期的输出容量:
StringBuilder out = new StringBuilder(bits.size() / 8 + 1);
使用按位运算代替parseInt()
,如下所示:
int i = 0;
int c = 0;
for(Boolean b: bits){
if (i > 0 && i % 8 == 0){
out.append((char) c);
c = 0;
}
c = (c << 1) | (b ? 1 : 0);
i++;
}
out.append((char) c); // Not sure about the desired behaviour here
答案 2 :(得分:2)
字符串连接速度很慢,特别是对于大型列表(因为字符串是不可变的,必须复制它们需要花费一些时间,每个副本也需要更多空间)。使用StringBuilder
代替String
进行追加。换句话说:buffer
和output
应为StringBuilder
个实例。
答案 3 :(得分:2)
正如其他人建议的那样 - 使用BitSet。对于其他人,我认为下面的方法非常有效:
public String toString() {
char[] bytes = new char[bits.size() / 8 + ((bits.size() % 8 > 0) ? 1 : 0)];
int bitCounter = 0;
int word = 0;
int byteCounter = 0;
for (boolean b : bits) {
word = (word << 1) | (b ? 1 : 0);
if (bitCounter == 7) {
bytes[byteCounter] = (char) word;
++byteCounter;
bitCounter = 0;
word = 0;
} else {
++bitCounter;
} // else
} // foreach
bytes[byteCounter] = (char) word;
return new String(bytes);
} // toString() method
这可能是一个不使用字节计数器的更好的选择:
public String toString() {
int size = bits.size() / 8 + ((bits.size() % 8 > 0) ? 1 : 0);
if (size == 0) {
return "";
} // if
char[] bytes = new char[size];
int bitCounter = 0;
int word = 0;
for (boolean b : bits) {
if (bitCounter % 8 == 0
&& bitCounter > 0) {
bytes[(bitCounter - 1) / 8] = (char) word;
word = 0;
} // if
word = (word << 1) | (b ? 1 : 0);
++bitCounter;
} // foreach
bytes[size - 1] = (char) word;
return new String(bytes);
} // toString() method
答案 4 :(得分:1)
尝试将缓冲区保留为int
。我的意思是
buffer = buffer << 1 + (((Boolean)it.next() == false) ? 0 : 1);
而不是
buffer += ((Boolean)it.next() == false) ? "0" : "1";
还可以使用StringBuilder
作为输出。这是一个很小的变化,但总是有点。
答案 5 :(得分:1)
尝试以下方法:
StringBuilder b = new StringBuilder();
int ch = 0;
int n = 0;
for (Boolean bit : bits) {
ch <<= 1;
if (bit) {
ch++;
}
if (++n == 8) {
b.append((char)ch);
n = 0;
ch = 0;
}
}
if (n > 0) {
b.append((char)ch);
}
System.out.println(b.toString());
答案 6 :(得分:0)
对缓冲区和输出变量使用StringBuffer或stringBuilder而不是String。
String vars是不可变的,因此每个操作都在堆中创建一个新实例,而StringBuilder和StringBuffer则不是。