Saya mencari metode di Jawa yang akan mengembalikan segmen array. Contohnya adalah untuk mendapatkan array byte yang berisi byte 4 dan 5 byte array. Saya tidak ingin harus membuat array byte baru di memori tumpukan hanya untuk melakukan itu. Saat ini saya memiliki kode berikut:
doSomethingWithTwoBytes(byte[] twoByteArray);
void someMethod(byte[] bigArray)
{
byte[] x = {bigArray[4], bigArray[5]};
doSomethingWithTwoBytes(x);
}
Saya ingin tahu apakah ada cara untuk melakukan di doSomething(bigArray.getSubArray(4, 2))
mana 4 adalah offset dan 2 adalah panjang, misalnya.
Jawaban:
Penafian: Jawaban ini tidak sesuai dengan batasan pertanyaan:
( Jujur, saya merasa jawaban saya layak dihapus. Jawaban oleh @ unique72 sudah benar. Imma membiarkan edit ini berlangsung sebentar dan kemudian saya akan menghapus jawaban ini. )
Saya tidak tahu cara untuk melakukan ini secara langsung dengan array tanpa alokasi tumpukan tambahan, tetapi jawaban lain menggunakan pembungkus sub-daftar memiliki alokasi tambahan hanya untuk pembungkus - tetapi tidak array - yang akan berguna dalam kasus array yang besar.
Yang mengatakan, jika seseorang mencari singkatnya, metode utilitas
Arrays.copyOfRange()
diperkenalkan di Java 6 (akhir 2006?):sumber
copyOfRange
. Jika itu sumber tertutup, mungkin itu bisa lewat. :)Arrays.asList(myArray)
delegasi ke yang baruArrayList(myArray)
, yang tidak menyalin array tetapi hanya menyimpan referensi. MenggunakanList.subList(start, end)
setelah itu membuatSubList
yang hanya mereferensikan daftar asli (yang masih hanya referensi array). Tidak ada salinan array atau isinya, hanya pembuatan wrapper, dan semua daftar yang terlibat didukung oleh array asli. (Saya pikir itu akan lebih berat.)sumber
Arrays
kebingungan dipanggilArrayList
, tetapi yang benar-benarList
sekitar array, sebagai lawanjava.util.ArrayList
yang akan membuat salinan. Tidak ada alokasi baru (dari konten daftar), dan tidak ada ketergantungan pihak ketiga. Saya yakin ini adalah jawaban yang paling benar.byte[]
dalam kasusnya). Yang akan Anda dapatkan hanyalahList<byte[]>
. Dan mengubahbyte[] bigArray
keByte[] bigArray
mungkin memaksakan overhead memori yang signifikan.sun.misc.Unsafe
kelas.Jika Anda mencari pendekatan aliasing gaya pointer, sehingga Anda bahkan tidak perlu mengalokasikan ruang dan menyalin data maka saya yakin Anda kurang beruntung.
System.arraycopy()
akan menyalin dari sumber Anda ke tujuan, dan efisiensi diklaim untuk utilitas ini. Anda perlu mengalokasikan array tujuan.sumber
array*copy*()
menggunakan kembali memori yang sama? Bukankah itu kebalikan dari apa yang diharapkan seorang penelepon?Salah satu caranya adalah dengan membungkus array
java.nio.ByteBuffer
, menggunakan fungsi put / get absolut, dan mengiris buffer untuk bekerja pada subarray.Misalnya:
Perhatikan bahwa Anda harus memanggil keduanya
wrap()
danslice()
, karenawrap()
dengan sendirinya hanya memengaruhi fungsi put / get relatif, bukan yang absolut.ByteBuffer
bisa agak sulit untuk dipahami, tetapi kemungkinan besar dilaksanakan secara efisien, dan layak untuk dipelajari.sumber
StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer, 0, readBytes))
Arrays.copyOfRange
?Arrays.copyOfRange
mungkin lebih efisien. Secara umum, Anda harus mengukur untuk kasus penggunaan spesifik Anda.Gunakan java.nio.Buffer's. Ini adalah pembungkus ringan untuk buffer dari berbagai jenis primitif dan membantu mengelola pengirisan, posisi, konversi, pemesanan byte, dll.
Jika byte Anda berasal dari Stream, NIO Buffer dapat menggunakan "mode langsung" yang menciptakan buffer yang didukung oleh sumber daya asli. Ini dapat meningkatkan kinerja dalam banyak kasus.
sumber
Anda bisa menggunakan ArrayUtils.subarray di apache commons. Tidak sempurna tetapi sedikit lebih intuitif daripada
System.arraycopy.
The downside adalah bahwa hal itu memperkenalkan ketergantungan lain ke dalam kode Anda.sumber
Saya melihat jawaban subList sudah ada di sini, tetapi di sini kode yang menunjukkan bahwa itu adalah sublist yang benar, bukan salinan:
Saya tidak percaya ada cara yang baik untuk melakukan ini secara langsung dengan array.
sumber
sumber
The
List
s memungkinkan Anda untuk menggunakan dan bekerja dengansubList
sesuatu transparan. Array primitif akan mengharuskan Anda untuk melacak semacam batas offset.ByteBuffer
s memiliki opsi yang sama seperti yang saya dengar.Sunting: Jika Anda bertanggung jawab atas metode yang berguna, Anda bisa mendefinisikannya dengan batas (seperti yang dilakukan dalam banyak metode terkait array di java itu sendiri:
Namun, tidak jelas apakah Anda mengerjakan sendiri elemen array, mis. Anda menghitung sesuatu dan menulis kembali hasilnya?
sumber
Salah satu opsi adalah untuk melewatkan seluruh array dan indeks awal dan akhir, dan beralih di antara mereka bukan iterasi atas seluruh array yang dilewati.
sumber
Referensi Java selalu menunjuk ke suatu objek. Objek memiliki header yang antara lain mengidentifikasi jenis beton (sehingga gips dapat gagal
ClassCastException
). Untuk array, awal objek juga termasuk panjang, data kemudian mengikuti segera setelah dalam memori (secara teknis implementasi bebas untuk melakukan apa yang diinginkan, tetapi akan sangat bodoh untuk melakukan hal lain). Jadi, Anda tidak bisa; t memiliki referensi yang menunjuk suatu tempat ke dalam array.Dalam C pointer arahkan ke mana saja dan ke apa saja, dan Anda bisa menunjuk ke tengah array. Tetapi Anda tidak dapat dengan aman membuang atau mencari tahu berapa lama array itu. Dalam D pointer berisi offset ke blok memori dan panjang (atau setara dengan pointer ke ujung, saya tidak ingat apa implementasi sebenarnya). Ini memungkinkan D untuk mengiris array. Dalam C ++ Anda akan memiliki dua iterator yang menunjuk ke awal dan akhir, tetapi C ++ agak aneh seperti itu.
Jadi kembali ke Jawa, tidak, kamu tidak bisa. Seperti yang disebutkan, NIO
ByteBuffer
memungkinkan Anda untuk membungkus array dan kemudian mengirisnya, tetapi memberikan antarmuka yang canggung. Tentu saja Anda bisa menyalin, yang mungkin jauh lebih cepat daripada yang Anda bayangkan. Anda dapat memperkenalkanString
abstraksi Anda sendiri- seperti yang memungkinkan Anda untuk mengiris array (implementasi Sun saat iniString
memilikichar[]
referensi plus offset dan panjang mulai, implementasi kinerja yang lebih tinggi hanya memilikichar[]
).byte[]
tingkat rendah, tetapi abstraksi berbasis kelas apa pun yang Anda pakai yang akan membuat berantakan sintaks yang mengerikan, sampai JDK7 (mungkin).sumber
substring
dalam HotSpot (lupa yang membangun mengubah ini). Mengapa Anda mengatakan bahwa JDK7 akan memungkinkan sintaks yang lebih baik daripada ByteBuffer?[]
notasi array pada tipe yang ditentukan pengguna, sepertiList
danByteBuffer
. Masih menunggu ...@ unique72 menjawab sebagai fungsi atau garis sederhana, Anda mungkin perlu mengganti Object, dengan tipe kelas yang ingin Anda 'slice'. Dua varian diberikan sesuai dengan berbagai kebutuhan.
sumber
Bagaimana dengan
List
bungkus tipis ?(Belum dicoba)
sumber
Byte
objek perpustakaan Java Orable untuk semuabyte
nilai di-cache. Jadi overhead tinju harus agak lambat.Saya perlu mengulang melalui akhir array dan tidak ingin menyalin array. Pendekatan saya adalah membuat Iterable di atas array.
sumber
Ini sedikit lebih ringan daripada Array.copyOfRange - tidak ada rentang atau negatif
sumber