バッファに読み込まれているデータを操作するクラスのライブラリがいくつかあります。配列を何度も何度もコピーすることを避けて、データの一部をより深く処理メソッドに渡すことは可能ですか?それは奇妙に聞こえますが、私の特定のケースでは、データをブロックに分割して別々の場所に個別に書き込む特別なライターがあります。したがって、System.arraycopyを実行し、必要なものを取得し、その新しいサブ配列。そして、これは何度も起こります。そのようなコードをリファクタリングする最良の方法は何ですか?
Javaの多くのクラスは、配列のサブセットをパラメーターとして受け入れます。例:Writer.write(char cbuf []、int off、int len)。おそらく、これはユースケースに十分です。
Arrays.asList(array).subList(x, y).
このメソッドは配列ではなく、List
を提供します。これははるかに柔軟です。
Javaでコピーせずにデータをラップして実際のarraを受信する yの実際の方法はありません。既存のメモリ上に新しい配列を作成することはできません。基本的に2つのオプションがあります。
_Java.nio.Buffer
_クラス階層、特に_Java.nio.ByteBuffer
_を使用できます。これは、配列全体またはサブ範囲でのバッファーの抽象化を提供します。多くの場合、それは人々が必要とするものです。これは、「ゼロコピー」フリップや柔軟なバイト領域表現など、多くの興味深い機能も提供します。
_Java.nio.ByteBuffer
_ を使用したラッピングの例を次に示します。これは必要なものに非常に近いはずです。少なくとも一部の操作では。
_byte [] a1 = {0, 0, 1, 0};
ByteBuffer buf = ByteBuffer.wrap(a1,1,2);
_
その後、buf
任意のByteBuffer
操作で実行できます。
警告です。buf.array()
は、すべての要素を含む元の_a1
_配列(バックエンド)を返します。
Byte []のような組み込み配列を使用する場合、Javaでサブ配列を宣言する方法はありません。理由は次のとおりです。配列の長さは、したがって、データをコピーしないサブアレイには、長さを格納できる場所がありません!そのため、基本型には前述の効率的なバイト配列コピーを使用でき、上位型(リスト)には使用可能なメソッドがあります。
String
クラスが取るのと同じアプローチを取ることができます。配列、開始オフセット、およびサブ配列へのアクセスを提供する終了オフセットから構成される不変オブジェクトのクラスを作成します。このようなオブジェクトのユーザーは、配列全体またはサブ配列の違いを知る必要はありません。コンストラクタは配列をコピーする必要はなく、配列参照とその境界を保存するだけです。
あなたは(ArrayList).subList(value1、value2)i beliveを使用できますが、おそらくあなたの場合に役立つでしょうか? ArrayListを使用する場合はもちろんです。
おそらく、配列を使用する代わりに、C#のArraySegmentと同様に、データをコピーするのではなく、元の配列のスライスへの参照を保持する別の型を使用する必要があります。これに対する追加の利点は、新しいインスタンスを作成せずに、必要に応じて元のアレイ上でスライスをシフトできることです。擬似コード:
public class ArraySegment<T> implements Iterable<T>
{
private int from, to;
private T[] original;
public ArraySegment<T>(T[] original, int from, int to)
{
//constructor stuff
}
public T get(int index)
{
return source[index + from];
}
public int size()
{
return to - from + 1;
}
@Override
public Iterator<T> iterator()
{
//Iterator that iterates over the slice
}
//Can support setters on from/to variables
}