89. Bagaimanakah ArrayList berbeza daripada LinkedList?
Ini adalah salah satu soalan yang paling popular, bersama-sama dengan soalan tentang struktur dalaman HashMap . Tiada temu bual yang lengkap tanpanya, jadi jawapan anda sepatutnya mudah didengari. Sebagai tambahan kepada yang jelas (mereka mempunyai nama yang berbeza), mereka berbeza dalam struktur dalaman mereka. Terdahulu, kami membincangkan struktur dalaman ArrayList dan LinkedList , jadi saya tidak akan menyelami butiran pelaksanaannya. Saya hanya akan mengingatkan anda bahawa ArrayList dilaksanakan menggunakan tatasusunan dalaman yang saiznya meningkat secara dinamik mengikut formula ini:<size of the current array> * 3 / 2 + 1
Selain itu, pelaksanaan LinkedList menggunakan senarai terpaut berganda dalaman, iaitu, setiap elemen mempunyai rujukan kepada elemen sebelumnya dan seterusnya, kecuali elemen pada permulaan dan akhir senarai. Penemuduga suka bertanya soalan ini seperti ini, "Yang lebih baik, ArrayList atau LinkedList ?" berharap dapat menangkap awak. Lagipun, jika anda mengatakan satu atau yang lain lebih baik, maka anda telah memberikan jawapan yang salah. Sebaliknya, anda harus menjelaskan situasi khusus yang anda bincangkan: mengakses elemen dengan indeks atau memasukkan di tengah-tengah senarai. Kemudian, bergantung pada jawapan mereka, anda boleh menerangkan mana yang lebih baik. Saya sebelum ini menerangkan cara ArrayList dan LinkedList berfungsi dalam setiap situasi. Mari kita ringkaskan ini dengan meletakkannya dalam satu baris untuk perbandingan: Menambah elemen (tambah)
-
Jika indeks tidak ditentukan, maka item baharu akan ditambah secara automatik ke penghujung untuk kedua-dua jenis senarai. Dalam LinkedList , elemen baharu akan menjadi ekor baharu (hanya sepasang rujukan akan ditulis semula, jadi kerumitan algoritma ialah O(1) ).
Kaedah tambah menambah elemen pada sel kosong terakhir dalam tatasusunan ( O(1) ).
-
Menambah item mengikut indeks biasanya bermaksud memasukkannya ke suatu tempat di tengah-tengah senarai. Dalam LinkedList , kaedah ini mula-mula akan mencari lokasi yang diingini dengan mengulangi unsur-unsur dari ekor dan kepala ( O(n/2) ) dan kemudian akan memasukkan nilai dengan menulis ganti rujukan unsur-unsur pada kedua-dua belah tempat elemen baru dimasukkan ( O(1) ). Kerumitan algoritma keseluruhan operasi ini ialah O(n/2) .
Dalam situasi yang sama (menambah mengikut indeks), ArrayList mencari lokasi yang dikehendaki ( O(1) ) dan kemudian mengalihkan semua elemen yang terletak ke kanan (termasuk elemen yang telah disimpan pada indeks yang ditentukan) ke kanan dengan satu (yang mungkin memerlukan penciptaan tatasusunan dalaman baharu dan menyalin elemen kepadanya) ( O(n/2) ). Kerumitan keseluruhan ialah O(n/2) .
-
Menambah elemen pada permulaan LinkedList adalah serupa dengan menambahkan elemen pada penghujung: elemen baharu menjadi kepala baharu ( O(1) ). Tetapi untuk ArrayList, operasi itu memerlukan memindahkan semua elemen ke kanan ( O(n) ).
90. Bagaimanakah ArrayList berbeza daripada HashSet?
Jika kami boleh membandingkan ArrayList dan LinkedList berdasarkan operasi demi operasi untuk menentukan yang mana satu lebih baik, kami tidak akan mendapati begitu mudah untuk membuat perbandingan sedemikian antara ArrayList dan HashSet , kerana ia adalah koleksi yang sama sekali berbeza. Anda boleh membandingkan satu pencuci mulut dengan pencuci mulut yang lain, tetapi membandingkan pencuci mulut dan hidangan berperisa adalah satu cabaran — ia amat berbeza. Namun, saya akan cuba menunjukkan beberapa perbezaan antara mereka:-
ArrayList melaksanakan antara muka Senarai manakala HashSet melaksanakan antara muka Set .
-
ArrayList membolehkan anda mengakses elemen mengikut indeks: operasi get mempunyai kerumitan algoritma O(1) , tetapi HashSet hanya membenarkan anda mengakses elemen yang diingini melalui lelaran, yang menghasilkan kerumitan algoritma antara O(1) hingga O(n) .
-
ArrayList membenarkan elemen pendua. Dalam HashSet , semua elemen adalah unik: sebarang percubaan untuk menambah elemen yang sudah ada dalam HashSet akan gagal (pendua disemak oleh kod cincang, oleh itu nama koleksi ini).
-
ArrayList dilaksanakan menggunakan tatasusunan dalaman, tetapi HashSet dilaksanakan menggunakan HashMap dalaman .
-
ArrayList mengekalkan susunan pemasukan elemen, tetapi HashSet ialah set tidak tertib dan tidak mengekalkan susunan elemen.
-
ArrayList membenarkan sebarang bilangan nilai nol, tetapi anda hanya boleh menambah satu nilai null pada HashSet ( lagipun, elemen mestilah unik).
91. Mengapakah Java mempunyai banyak pelaksanaan tatasusunan dinamik yang berbeza?
Ini lebih kepada persoalan falsafah. Kita juga boleh bertanya mengapa mereka menghasilkan begitu banyak teknologi baharu dan pelbagai? Untuk kemudahan. Dan perkara yang sama adalah benar tentang sejumlah besar pelaksanaan tatasusunan dinamik. Tiada satu pun daripada mereka boleh dipanggil pelaksanaan terbaik atau ideal. Setiap mempunyai kelebihan situasi tertentu. Tugas kami adalah untuk mengetahui perbezaan dan kekuatan/kelemahan mereka agar dapat menggunakan koleksi yang paling sesuai untuk sebarang situasi tertentu.92. Mengapakah Java mempunyai banyak pelaksanaan storan nilai kunci yang berbeza?
Di sini keadaannya adalah sama seperti pelaksanaan tatasusunan dinamik. Pasti tidak ada yang lebih baik secara universal daripada yang lain: masing-masing mempunyai kekuatan dan kelemahan. Dan kita mesti memanfaatkan kekuatan mereka, sudah tentu. Contoh: pakej serentak, yang mempunyai banyak kelas berbilang benang, mempunyai koleksi Serentak sendiri . Kelas ConcurrentHashMap mempunyai kelebihan berbanding HashMap standard dari segi keselamatan apabila bekerja dengan data dalam persekitaran berbilang benang, tetapi itu datang dengan kos prestasi yang lebih perlahan. Dan pelaksanaan yang bukan pilihan terbaik dalam apa jua keadaan secara beransur-ansur tidak lagi digunakan. Contohnya: Hashtable , yang pada asalnya bertujuan untuk menjadi HashMap selamat benang , telah dilupakan dan tidak digunakan lagi, kerana ConcurrentHashMap lebih baik daripada Hashtable apabila bekerja dalam persekitaran berbilang benang.93. Bagaimanakah cara saya mengisih koleksi elemen?
Perkara pertama yang perlu dikatakan ialah kelas yang mewakili elemen koleksi mesti melaksanakan antara muka Sebanding , yang terdiri daripada kaedah compareTo . Atau anda memerlukan kelas yang melaksanakan antara muka Pembanding , termasuk kaedah perbandingannya . Kedua-dua kaedah menunjukkan cara membandingkan objek jenis tertentu. Ini penting semasa mengisih, kerana algoritma pengisihan perlu memahami prinsip apa yang hendak digunakan untuk membandingkan elemen. Ini dilakukan terutamanya dengan melaksanakan Comparable secara langsung dalam kelas yang anda ingin susun. Menggunakan Comparator adalah kurang biasa. Katakan anda menggunakan kelas daripada sesetengah perpustakaan dan ia tidak melaksanakan Comparable , tetapi anda perlu mengisih koleksi objeknya. Memandangkan anda tidak boleh menukar kod kelas ini (kecuali dengan melanjutkannya), anda boleh menulis pelaksanaan Comparator yang menunjukkan cara membandingkan objek kelas. Dan satu lagi contoh. Jika anda perlu mengisih objek daripada jenis yang sama dengan cara yang berbeza, maka anda boleh menulis berbilang pelaksanaan Comparator untuk digunakan dalam situasi yang berbeza. Sebagai peraturan, banyak kelas luar kotak, contohnya String , sudah melaksanakan antara muka Setanding . Ini bermakna anda tidak perlu risau tentang cara membandingkan kelas ini. Anda boleh teruskan dan gunakannya. Cara pertama dan paling jelas ialah menggunakan kelas TreeSet atau TreeMap . Kelas-kelas ini menyimpan elemen dalam susunan disusun berdasarkan pembanding yang dilaksanakan oleh elemen kelas. Jangan lupa bahawa TreeMap mengisih kunci, bukan nilai. Jika anda menggunakan Comparator dan bukannya Comparable , maka anda perlu menghantar objek Comparator kepada pembina koleksi apabila anda menciptanya:TreeSet treeSet = new TreeSet(customComparator);
Tetapi bagaimana jika anda mempunyai jenis koleksi yang berbeza? Bagaimana anda menyusunnya? Dalam kes ini, cara kedua kelas utiliti Koleksi — kaedah sort() — adalah sesuai. Kaedah ini statik, jadi anda hanya perlu memasukkan nama kelas dan kemudian masukkan senarai untuk diisih. Sebagai contoh:
Collections.sort(someList);
Jika anda menggunakan pelaksanaan Comparator dan bukannya Comparable , maka anda perlu menyerahkannya sebagai hujah kedua:
Collections.sort(someList, customComparator);
Operasi ini akan mengubah susunan dalaman elemen dalam senarai yang diluluskan: senarai akan diisih menggunakan pembanding. Ambil perhatian bahawa senarai yang diluluskan mesti boleh diubah, jika tidak kaedah akan gagal dan membuang UnsupportedOperationException . Pilihan ketiga ialah menggunakan kaedah diisih kelas Stream , yang menyusun elemen koleksi. Jika kita menggunakan Comparable :
someList = someList.stream().sorted().collect(Collectors.toList());
Jika kita menggunakan Comparator :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
Cara keempat ialah dengan melaksanakan algoritma isihan secara manual, contohnya, isihan gelembung
atau isihan gabungan
.
Kelas objek. equals() dan hashCode()
94. Berikan penerangan ringkas tentang kelas Objek di Jawa.
Dalam bahagian kedua semakan, kami telah membincangkan kaedah kelas Objek . Di sini saya akan mengingatkan anda bahawa kelas Objek adalah nenek moyang setiap kelas di Jawa. Ia mempunyai 11 kaedah, yang seterusnya diwarisi oleh semua kelas.95. Apakah equals() dan hashCode() yang digunakan dalam Java?
hashCode() ialah kaedah kelas Objek yang diwarisi oleh semua kelas. Tugasnya adalah untuk menjana nombor yang mewakili objek tertentu. Contoh kaedah dalam tindakan ini boleh didapati dalam HashMap , di mana ia dipanggil pada objek utama untuk mendapatkan kod cincang tempatan, yang akan menentukan baldi (sel tatasusunan dalaman) pasangan nilai kunci akan disimpan di dalamnya. Juga, kaedah ini biasanya digunakan dalam kaedah equals() sebagai salah satu cara utamanya untuk mengenal pasti objek. equals() ialah kaedah kelas Objek yang tugasnya adalah untuk membandingkan objek dan menentukan sama ada ia sama. Kaedah ini digunakan di mana-mana kita perlu membandingkan objek, kerana operator perbandingan == standard tidak sesuai untuk objek, kerana ia hanya membandingkan rujukan objek.96. Beritahu kami tentang kontrak antara equals() dan hashCode() dalam Java?
Mula-mula, izinkan saya katakan bahawa untuk kaedah equals() dan hashCode() berfungsi dengan betul, kaedah tersebut mesti diganti dengan betul. Pelaksanaan baharu mereka mesti mengikut peraturan ini:- Objek yang sama yang nilainya sama dengan benar mesti mempunyai kod cincang yang sama.
- Objek dengan kod cincang yang sama tidak semestinya sama.