簡體   English   中英

Integer.toString(myInt).getBytes(US_ASCII)是否有更快的替代方案?

[英]Is there is a faster alternative for Integer.toString(myInt).getBytes(US_ASCII)?

用戶向我發送byte / short / int / long值。 我必須將它作為POST HTTP請求的一部分發送,我必須將數字作為字符串發送。

所以現在我做下一個:

//simplified version
byte[] data = Integer.toString(myInt).getBytes(US_ASCII);
sendPost(data);

我正在尋找更快的替代方案

Integer.toString(myInt).getBytes(US_ASCII);

因為此流創建char[]Stringbyte[]對象。 雖然我只需要byte[] 我想知道是否有更快/更好的替代方案。

這個解決方案非常簡單。

import java.util.Arrays; // Needed only for demo purposes

public class LongToBytes
{
  private static final byte ZERO = '0';
  private static final byte MINUS = '-';

  public static byte[] convert(long value)
  {
    // -------------------------------------
    // Manage some particular value directly
    // abs(Long.MIN_VALUE) remains negative
    // -------------------------------------
    if ((value >= 0) && (value < 10))
      return (new byte[]{(byte)(ZERO + value)});
    else if ((value > -10) && (value < 0))
      return (new byte[] {MINUS, (byte)(ZERO - value)});
    else if (value == Long.MIN_VALUE)
      return (Long.toString(value).getBytes());

    // -----------------------------------------------------------------
    // Initialize result
    // The longest value (Long.MIN_VALUE+1) is composed of 20 characters
    // -----------------------------------------------------------------
    byte[] array;
    array = new byte[20];

    // ---------------------------
    // Keep track of eventual sign
    // ---------------------------
    boolean negative;
    negative = (value < 0);
    if (negative)
      value = -value;

    // ----------------------
    // Fill array (backwards)
    // ----------------------
    int size;
    size = 0;
    while (value > 0)
    {
      array[size] = (byte)((value % 10) + ZERO);
      size++;
      value /= 10;
    }

    // -------------------
    // Add sign eventually
    // -------------------
    if (negative)
    {
      array[size] = MINUS;
      size++;
    }

    // -------------------------------------------------------------
    // Compose result, giving it the correct length and reversing it
    // -------------------------------------------------------------
    byte[] result;
    int    counter;
    result = new byte[size];
    for (counter = 0; counter < size; counter++)
      result[size - counter - 1] = array[counter];

    // ----
    // Done
    // ----
    return (result);

  } // convert

  public static void main(String[] args)
  {
    try
    {
      long value;
      value = Long.parseLong(args[0]);
      System.out.println(value);
      System.out.println(Arrays.toString(convert(value)));
    }
    catch (Exception exception)
    {
      exception.printStackTrace();
    }
  }

} // class LongToBytes

UPDATE
我使用System.nanoTime()作為秒表,在超過100.000.000的循環中分別檢查了兩種方式(上面的方法和Long.toString().getBytes() )的性能。

傳遞0,上述方法快約500倍。
相對較小的值(在-10.000和10.000之間)具有約60%的增益。
巨大的值(靠近Long.MIN_VALUE和Long.MAX_VALUE)的增益約為40%。

更新2
分別管理特定值(介於-9和9之間以及值Long.MIN_VALUE),情況稍微好一些。
我更新了方法的實現。

您可以將整數直接格式化為字節數組,這是一個簡單的操作,因為數字在ASCII diapason中從48到57

例如:

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class FormatInteger {

    private static final byte ZERRO = 48;
    private static final byte MINUS = 45;
    private static String MIN_VALUE = "-9223372036854775808";
    private static String MAX_VALUE = "9223372036854775807";

    public static void toAsciiString(long val, byte[] to) {
        if (0 == val) {
            to[0] = ZERRO;
            to[1] = 0;
        } else if (val == Long.MIN_VALUE) {
            byte min[] = MIN_VALUE.getBytes(StandardCharsets.US_ASCII);
            System.arraycopy(min, 0, to, 0, min.length);
        } else if(val == Long.MAX_VALUE) {
            byte max[] = MAX_VALUE.getBytes(StandardCharsets.US_ASCII);
            System.arraycopy(max, 0, to, 0, max.length);
        } else {
            boolean sign = val < 0;
            if (sign) {
                val *= -1L;
            }
            int pos = to.length - 1;
            to[pos--] = 0;
            while (val != 0) {
                to[pos--] = (byte) (ZERRO + (val % 10));
                val /= 10;
            }
            if (sign) {
                to[pos] = MINUS;
            } else {
                ++pos;
            }
            System.arraycopy(to, pos, to, 0, (to.length - pos) );
            Arrays.fill(to, (to.length - pos), to.length - 1, (byte) 0);
        }
    }

    public static void main(String[] args) {
        byte[] tmp = new byte[21];
        toAsciiString(0,tmp);
        System.out.println( new String(tmp, StandardCharsets.US_ASCII) );
        toAsciiString(1234567890,tmp);
        System.out.println( new String(tmp, StandardCharsets.US_ASCII) );
        toAsciiString(-1234567890,tmp);
        System.out.println( new String(tmp, StandardCharsets.US_ASCII) );
        toAsciiString(Long.MIN_VALUE, tmp);
        System.out.println(new String(tmp, StandardCharsets.US_ASCII));
        toAsciiString(Long.MAX_VALUE, tmp);
        System.out.println(new String(tmp, StandardCharsets.US_ASCII));
    }

}

只是一個想法

int digits = getNumberOfDifits(number);

byte[] out = new byte[digits];

for (int j = digits - 1; j >= 0; j--) {
    int rem = number % 10;
    out[j] = getByteForDigit(rem);
    number = number / 10;
}

return out

堆中沒有輔助對象,堆棧中處理的所有內容

這是一種可能性。 這始終比Integer.toString()方法更快。

   public static byte[] getBytes(long value) {
      int sign = 0;
      if (value < 0) {
         sign = 1;
         value = -value;
      }

      long temp = 10L;
      int chars = 1;
      for (int i = 1; i < 20; i++) {
         if (value < temp) {
            chars = i + sign;
            break;
         }
         temp *= 10;
      }


      byte[] bytes = new byte[chars];

      int i = 0;
      while (value > 0) {
         bytes[chars - i - 1] = (byte) ((value % 10) + '0');
         value /= 10;
         i++;
      }

      if (sign == 1) {
         bytes[0] = '-';
      }
      return bytes;
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM