2015-05-29 19 views
5

假設我有一個方法void foo(byte[] bytes)需要一個字節數組作爲其參數。在Protobuf中,字節數組的Java類型Howerver是ByteString。我可以使用byte[] toByteArray()獲取字節數組。但問題是這種方法使用拷貝來構建新的陣列,這是相對昂貴的。我寧願直接返回底層數組,或者返回一個視圖。協議緩衝區:從ByteString獲取字節數組而不復制

是否有任何API,或性能處罰是可以接受的?

+0

foo(byte [] bytes)方法做什麼?你能改變它的實現嗎? – kostya

+0

@kostya您的意思是我可以使用'ByteString#writeTo(OutputStream)'而不是?但我真的希望我的模塊相互分離。 – duleshi

+0

是的,就像'writeTo'。 'OutputStream'是標準庫中的一個類,所以你仍然可以保持foo()方法protobuf免費。 'ByteString'的Javadocs清楚地表明你所要求的是不可能的:像'String'一樣,ByteString的內容永遠不會被改變,即使在數據競爭或客戶端代碼中API使用不正確的情況下。 – kostya

回答

4

通常這是不可能的,因爲在ByteString的某些子類中可能沒有這樣的數組。 BoundedByteString可以包含更大的數組,因此需要進行復制才能獲得正確大小的數組。 RopeByteString由其他字節串組成,因此需要複製以將其內容放入一個數組中。 LiteralByteString將其內容存儲在正確大小的數組中,但它不提供直接訪問它的方法。

但最有可能的toByteArray()將足夠快,因爲您的需求System.arraycopy()是非常快的。

如果您確實因長陣列複製而導致性能問題,並且您不想直接通過ByteString,請參閱asReadOnlyByteBuffer()asReadOnlyByteBufferList()方法。他們將ByteString內容包裝到ByteBuffer中而不復制它們。

2

你不能從一個ByteString沒有byte[]複製,因爲這將允許你修改ByteString的內容,這意味着ByteString再也不能保證它是不可改變的。這很像爲什麼你不能在不復制的情況下從String得到char[],即使String實際上是由char[]支持的。這可能是一個安全問題:在安全域之間傳遞StringByteString時,重要的是接收方可以知道發件人在使用它時並未從其下方修改字符串。

但是,您可以撥打asReadOnlyByteBufferList()獲得代表底層數據的ByteBuffer,因爲ByteBuffer強制執行不變性。