Pertanyaan Kapan array generik benar-benar diperlukan - sebuah kasus


Q ini adalah untuk mencari contoh kasus di mana array generik mutlak diperlukan.

Generik dan array "tidak tercampur dengan baik".

Apakah ada kasus di mana generik ArrayList tidak akan melakukan - array generik tidak memiliki pengganti dan harus digunakan.

Java yang efektif daun pintu terbuka untuk array generik mengatakan bahwa mungkin ada kasus di mana array generik diperlukan.

Saya telah menggunakan ArrayList tanpa ada kekurangan dan tidak bisa memikirkan kasus seperti ini.

TIA.

Catatan: Saya telah melihat ini:

Bersamaan dengan beberapa diskusi lainnya.


24
2018-05-13 14:13


asal


Jawaban:


Beberapa poin:

  • Jika Anda memiliki beberapa pustaka "warisan", maka Anda terikat dengan jenis yang mereka gunakan. Ini bisa jadi array.

  • Jika Anda menangani kode asli maka array akan menjadi cara yang lebih alami untuk bertukar data dengan kode asli.

  • Jika Anda mengakses data biner (misalnya file suara atau yang serupa), maka menggunakan array dapat membantu.

  • Jika Anda menangani data biner dalam jumlah besar maka array bisa lebih efisien.

Jadi ada banyak alasan mengapa suatu array dapat membantu (terutama dengan tipe primitif).

Jika Anda hanya menangani objek maka paling mudah digunakan List.


7
2018-05-13 14:42



Saya akan mengatakan bahwa Bloch berarti mudah dari pada perlu, array adalah struktur yang lebih sederhana, lebih mudah untuk ditangani.

Sebagai struktur data, dari sudut pandang fungsi, ArrayList dapat dipertukarkan dengan array.

Array jelas lebih ramping ingatan-bijaksana tetapi memerlukan upaya tambahan untuk mendapatkan beberapa fungsi dasar (yaitu array manual mengubah ukuran ketika array asli tidak cukup besar untuk menahan elemen baru) tetapi fungsi-fungsi lain sudah disediakan oleh runtime (Arrays kelas).

ArrayLists didukung oleh aktual Object Array sehingga tidak ada banyak perbedaan kinerja yang bijaksana, untuk operasi umum seperti mencari dan menyortir (ketika menggunakan algoritma yang sama).


6
2018-05-13 14:42



Sebuah ArrayList membutuhkan sejumlah kecil memori tambahan dibandingkan dengan array. Ini jelas benar sebagai ArrayList diimplementasikan sebagai pembungkus di sekitar array. Dengan perkiraan kasar saya, sebuah ArrayList akan mengkonsumsi tambahan 16 byte.

Dalam keadaan normal, ini tidak perlu dikhawatirkan. Tetapi jika Anda membuat sejumlah besar array (jutaan / miliaran), itu bisa berpotensi membuat perbedaan.

Ada juga kasus array primitif. ArrayList dibatasi oleh aturan untuk koleksi, sehingga tidak dapat menyimpan elemen primitif, hanya pembungkus objek yang sesuai. Jadi misalnya, byte[] mengkonsumsi 1 byte per elemen, tapi ArrayList<Byte> mengkonsumsi 4 byte per elemen. Ini dapat membuat perbedaan jika array Anda berpotensi sangat besar.


3
2018-05-13 14:46



Beberapa pemikiran longgar:

array adalah tipe data dasar yang diperlukan dalam bahasa imperatif apa pun (mungkin dalam bentuk terselubung). Tanpa array, bagaimana kita bisa menerapkan ArrayList? :)

Namun, kita bisa menyamar array sebagai tipe "normal". Sebagai contoh, kita bisa memperkenalkan intrinsik lang.lang.Array<E> ketik yang melakukan berbagai hal, dan menghilangkan arus array ketik di Java. (Mengabaikan array primitif, itu topik yang lain). Semuanya akan berjalan dengan baik.

Namun, kita tidak memiliki kemewahan untuk "memperbaiki" dan "membersihkan" bahasa dengan cara yang memecah kompatibilitas ke belakang.

Sebelum pengenalan generik, array dapat dilihat sebagai obat generik orang miskin. Kami tidak bisa mengungkapkannya ArrayList<String>, tetapi kita bisa melakukannya String[]. Itulah sebabnya banyak API lama mengembalikan array, bukan beberapa jenis koleksi, karena array lebih aman. array bahkan co-varian ... semacam.

Setelah pengenalan generik, kasus penggunaan untuk array menjadi jauh lebih sedikit. Biasanya, Anda harus menghindari penggunaan array dalam API publik. (Tentu saja, kecuali var-arg foo(Bar...) yang merupakan array di bawah tenda)

Namun dalam kode implementasi, kita masih perlu  array, itu struktur data dasar untuk membangun struktur data yang lebih kompleks. Untuk alasan tersebut ArrayList jelas lebih kembung dalam banyak kasus.

Sekarang, pertanyaannya adalah, untuk mengimplementasikan sesuatu seperti ArrayList<E>, sebaiknya kita menggunakan a E[], atau Object[] secara internal? Karena penghapusan, E[] lebih merepotkan - seperti kata pepatah "generik dan array tidak bercampur dengan baik". Jadi lupakan saja, gunakan saja Object[] dan lakukan pemeran bila diperlukan.


3
2018-05-13 14:43



Umumnya, ArrayList dianggap lebih menguntungkan dari array. Ini menyediakan fungsi yang sama, sementara mengintegrasikan lebih baik, terutama dengan jenis lain dari Java Collection API.

Oleh karena itu, penggunaan array dapat dihasilkan dari persyaratan khusus. Di satu sisi, seseorang mungkin ingin menggunakan perpustakaan (atau lainnya Kode pihak ketiga) yang membutuhkan array.

Di sisi lain, masih ada array berkinerja lebih baik dari sebuah ArrayList. Saya membuat sebuah Inti yang membandingkan penggunaan suatu ArrayList<Integer> ke sebuah int[]. (Perhatikan, bahwa Anda tidak dapat menggunakan primitif dengan ArrayLists.) Hasil rata-rata untuk membuat 1.000.000 elemen acak dan menemukan maksimumnya di komputer saya:

Test case CREATE_ARRAY average time: 25.93 ms
Test case CREATE_ARRAY_LIST average time: 44.06 ms
Test case MAX_OVER_ARRAY average time: 1.44 ms
Test case MAX_OVER_ARRAY_LIST average time: 5.86 ms

Jadi, kita berputar-putar 4 kali lebih lambat dengan sebuah ArrayList. Namun, dalam normal menggunakan kasus, ini dapat dengan aman dianggap sebagai optimasi mikro. Sebagian besar kasus menggunakan permintaan kualitas kode atas peningkatan kinerja tersebut.


3
2018-05-13 14:52



[...] mengatakan itu di sana mungkin menjadi kasus di mana array generik adalah   perlu.

Sepertinya Joshua Bloch hanya ingin aman memungkinkan kemungkinan bahkan jika dia tidak mengetahuinya.

Mengapa seorang penulis menyebutkan titik seperti itu tanpa contoh jika dia tahu ada satu?

Asumsi ArrayList menyimpannya nilai itu sendiri dalam array dan hanya menyediakan metode yang berguna sehingga Anda tidak perlu menulis ulang semuanya, saya akan sangat terkejut untuk menghadapi kasus di mana Anda tidak dapat mencapai sesuatu dengan ArrayListtetapi bisa mencapai dengan array.

Struktur datanya sendiri sama, ingat Arrays.asList dan ArrayList.toArray


2
2018-05-13 15:51



Saya memikirkan beberapa hal segera ketika saya membaca pertanyaan itu.

Satu: Jika Anda menggunakan Java Micro Edition, Anda mungkin tidak memilikinya ArrayList tersedia untuk Anda. Hal semacam ini cukup umum jika Anda pernah bekerja pada kode warisan. Menulis dalam. Net 1.1 atau 2.0 terasa sangat mirip dengan memotong lengan Anda dibandingkan dengan 4.0 dan yang lebih baru (menurut saya). Java Micro Edition serupa - Jika Anda terbiasa dengan Java 6+ maka J2ME terasa sangat terbatas. Pertanyaan ini membahasnya sedikit, tapi saya pikir saya akan pergi dengan array biasa daripada menggunakan vektor (yang menurut benang itu disinkronkan ... saya belum menggali lebih dalam dari itu).

Dua: Jika Anda menggunakan sistem tertanam dan harus memiliki kontrol ketat terhadap ukuran larik. Jawaban lain menyentuh ini sedikit. IIrc fungsi default dari ArrayList adalah menggandakan ukuran ketika ukurannya berubah, tapi saya kesulitan menemukan kutipan yang tepat untuk itu. Pada sistem embedded dengan memori yang sangat terbatas, itu tidak akan mengejutkan saya jika resize seperti itu mencoba mengalokasikan lebih dari semua memori dalam sistem (misalnya array Anda mengambil 75% dari semua memori sistem, pada mengubah ukuran itu akan mencoba untuk mengambil 150% dari memori). Jika Anda menggunakan larik dan secara manual mengendalikan semua pengubahan ukuran, maka ini menjadi tidak masalah.


1
2018-05-13 17:28