如何有效地将String序列化为现有的ByteBuffer?

时间:2017-05-02 09:05:27

标签: java string bytebuffer

似乎ByteBuffer将创建一个新的字节数组,因此有一个额外的内存副本。我可以直接将字符串编码为void putString(ByteBuffer bb, String s) { byte[] arr = s.getBytes(StandardCharsets.UTF_8); bb.put(arr); } 而没有中间字节数组吗?

例如:

add_filter( $filter_name, array( __CLASS__, 'filter_value_save' ), PHP_INT_MIN, 1 );
        add_filter( $filter_name, array( __CLASS__, 'filter_value_restore' ), PHP_INT_MAX, 1 );

        return true;
    }

    public static function remove_filter_protection( $filter_name ) {
        if ( ! has_filter( $filter_name, array( __CLASS__, 'filter_value_restore' ) ) ) {
            return false;
        }
        remove_filter( $filter_name, array( __CLASS__, 'filter_value_save' ), PHP_INT_MIN );
        remove_filter( $filter_name, array( __CLASS__, 'filter_value_restore' ), PHP_INT_MAX );

这段代码将创建一个字节数组,将字符串编码为此字节数组,然后将字节数组的内容复制到ByteBuffer。 我认为字节数组不是必需的,它会带来GC和额外的内存复制。

4 个答案:

答案 0 :(得分:2)

您可以使用CharsetEncoder直接写入ByteBuffer

static void putString(ByteBuffer buffer, String str, Charset charset) {
    CharsetEncoder encoder = charset.newEncoder();
    encoder.encode(CharBuffer.wrap(str), buffer, true);
    encoder.flush(buffer);
}

您有责任确保分配足够的空间。您还可以检查encode()方法的结果,看看它是否成功。

答案 1 :(得分:1)

我无法想到一种完全消除中间字节数组的简单方法。

但是如果你因为字符串很大而担心这个问题,你可以把它分成几块:

  for(offset=0; offset<str.length(); offset+=chunkSize) {
      String chunk = str.substring(offset, offset+chunkSize);
      byteBuffer.put(chunk.getBytes(StandardCharsets.UTF_8));
  }

但是,如果您的输入字符串足够大以至于需要进行此优化,那么您的程序的整体架构可能是错误的。

除非您在分析时看到异常情况,否则担心GC性能。在高效的GC中,JRE是辉煌的

答案 2 :(得分:0)

不,这是不可能的。字符串对象没有编码。

答案 3 :(得分:0)

String对象按目的是不可变的。该类的整个想法是允许操纵任何底层数据结构(主要是出于安全性和性能优化的原因)。

从这个意义上说:没有其他更好的方法来获取构成Java中字符串对象的字节。