这个Java算法如何更快

发布于 2024-12-28 17:12:58 字数 776 浏览 0 评论 0原文

我有一个循环,它将布尔 LinkedList 按 8 位分割并返回缓冲区中每个字节的 ASCII 值。该函数返回字符串缓冲区。

如果 LinkedList 的大小很大,那么这段代码会非常慢。我尝试用简单的循环来更改迭代器,但它仍然很慢。

这个算法怎么能真正快呢?也许使用多线程?

注意: linkedList 的大小并不总是能被 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;
}

I have this loop which splits a Boolean LinkedList by 8 bits and return the ASCII value of each byte in a buffer. The function return the string buffer.

This code is extremely slow if the LinkedList's size is big. I try to change the Iterator with a simple looping, but it's still slow.

How can this algorithm be really fast ? Maybe with multi-threading ?

Note: The size of the linkedList is not always divisible by 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

甜警司 2025-01-04 17:12:58

这些建议将为您提供足够的性能,同时保持代码简单和可读。首先使用这些更改进行测试,如果不满足您的性能要求,则慢慢引入其他答案中建议的优化技术

  1. 使用 BitSet 而不是 LinkedList
  2. 使用 StringBuilder输出;而不是字符串输出;
  3. 使用StringBuilder缓冲区;而不是字符串缓冲区;
  4. 使用Integer.valueOf() 而不是Integer.parseInt。我认为 valueOf 对低于 128 的值使用缓存。

These suggestions will give you enough performance still keeping the code simple and readable. First test using these changes and if doesn't meet your performance requirements then slowly introduce optimization techniques suggested in other answers

  1. Use BitSet instead of LinkedList<Boolean>
  2. use StringBuilder output; instead of String output;
  3. use StringBuilder buffer; instead of String buffer;
  4. Use Integer.valueOf() instead of Integer.parseInt. valueOf uses cache for values below 128 i think.
离旧人 2025-01-04 17:12:58
  1. 使用使用预期输出容量初始化的StringBuilder

    StringBuilder out = new StringBuilder(bits.size() / 8 + 1);
    
  2. 使用按位运算而不是parseInt(),如下所示:

    int i = 0;          
    整数c=0;
    for(布尔值 b: 位){
        if (i > 0 && i % 8 == 0){
            out.append((char) c);
            c = 0;
        }
        c = (c << 1) | (b?1:0);
        我++;
    }
    out.append((char) c); // 不确定这里想要的行为
    
  1. Use StringBuilder initialized with expected capacity for output:

    StringBuilder out = new StringBuilder(bits.size() / 8 + 1);
    
  2. Use bitwise operations instead of parseInt(), something like this:

    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
    
余生一个溪 2025-01-04 17:12:58

字符串连接速度很慢,尤其是对于大型列表(因为字符串是不可变的,因此必须复制它们,这需要一些时间,并且每个副本也需要更多空间)。使用 StringBuilder 而不是 String 进行追加。换句话说:bufferoutput应该是StringBuilder实例。

String concatenation is slow especially for large lists (since strings are immutable they have to be copied around which takes some time and each copy requires more space as well). Use a StringBuilder instead of a String to append to. In other words: buffer and output should be StringBuilder instances.

蓝颜夕 2025-01-04 17:12:58

正如其他人建议的那样 - 使用 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

As others suggested - use BitSet. For the rest, I think the method below is pretty efficient:

    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

Here is possibly a better alternative that does not use byte counter:

        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
三生路 2025-01-04 17:12:58

尝试将缓冲区保持为 int。我的意思

 buffer = buffer << 1 + (((Boolean)it.next() == false) ? 0 : 1);

是代替

 buffer += ((Boolean)it.next() == false) ? "0" : "1";

Also use StringBuilder 进行输出。这是一个很小的变化,但总是一点点。

Try to keep buffer as an int. I mean

 buffer = buffer << 1 + (((Boolean)it.next() == false) ? 0 : 1);

instead of

 buffer += ((Boolean)it.next() == false) ? "0" : "1";

Also use StringBuilder for output. This is a small change here but always a bit.

水水月牙 2025-01-04 17:12:58

请尝试以下操作:

 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());

Try the following:

 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());
私藏温柔 2025-01-04 17:12:58

使用 StringBuffer 或 stringBuilder 而不是 String 作为缓冲区和输出变量。

字符串变量是不可变的,因此每个操作都会在堆中创建一个新实例,而 StringBuilder 和 StringBuffer 则不然。

Use StringBuffer or stringBuilder instead of String for your buffer and output vars.

String vars are immutable, so every operations creates a new instance in heap, while StringBuilder and StringBuffer are not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文