CodeGym /Blog Java /rawak /Meneroka soalan dan jawapan daripada temu duga kerja untu...
John Squirrels
Tahap
San Francisco

Meneroka soalan dan jawapan daripada temu duga kerja untuk jawatan pembangun Java. Bahagian 10

Diterbitkan dalam kumpulan
Hai! Berapa jam yang diperlukan untuk menjadi mahir dalam sesuatu? Saya sering mendengar sesuatu seperti: "Untuk menjadi mahir dalam apa sahaja, anda perlu menghabiskan 10,000 jam untuknya." Itu nombor yang menakutkan, bukan? Meneroka soalan dan jawapan daripada temu duga kerja untuk jawatan pembangun Java.  Bahagian 10 - 1Namun, saya tertanya-tanya adakah ia benar. Dan saya sentiasa cuba memikirkan berapa jam saya telah melabur dalam menguasai seni pengaturcaraan. Dan apabila saya melintasi garisan istimewa 10,000 jam itu dan menjadi seorang sarjana, adakah saya akan merasakan perbezaannya? Atau adakah saya sudah lama melintasi garisan itu tanpa disedari? Sama ada cara, anda tidak perlu melaburkan banyak masa untuk menjadi seorang pengaturcara. Yang penting gunakan masa dengan bijak. Matlamat utama anda adalah untuk mendapatkan temu duga. Dan dalam temu bual, bakal pembangun perisian pertama kali ditanya tentang teori, jadi itu perlu menjadi kekuatan. Malah, semasa anda bersedia untuk temu duga, tugas anda adalah untuk menemui semua jurang dalam pengetahuan teori asas Java dan kemudian mengisinya. Hari ini saya di sini untuk membantu anda melakukan perkara itu, kerana hari ini kami akan meneruskan semakan kami terhadap soalan temu bual yang paling popular. Baik, mari teruskan!

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. Meneroka soalan dan jawapan daripada temu duga kerja untuk jawatan pembangun Java.  Bahagian 10 - 2Sebaliknya, 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)
  1. 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) ).

  2. 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) .

  3. 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) ).

Intinya ialah untuk LinkedList kerumitan algoritma akan berjulat dari O(1) hingga O(n/2) . Pemerhatian lain ialah semakin dekat sisipan dengan penghujung atau permulaan senarai, semakin cepat ia. Untuk ArrayList , kerumitan algoritma berjulat dari O(1) hingga O(n) , dan semakin dekat sisipan dengan penghujung senarai, semakin pantas ia. Menetapkan elemen (set) Operasi ini menulis elemen ke kedudukan yang ditentukan dalam senarai, menimpa sebarang elemen sedia ada. Dalam LinkedList , operasi ini serupa dengan menambah, kerana cabaran terbesar di sini ialah mencari lokasi elemen. Elemen sedia ada ditimpa dengan mengemas kini sepasang rujukan, jadi sekali lagi kita mempunyai kerumitan algoritma yang berbeza dari O(1) hingga O(n/2) , bergantung pada jarak kedudukan yang diingini dari penghujung atau permulaan senarai. Tetapi untuk ArrayList , operasi ini mencari sel yang dikehendaki mengikut indeks dan menulis elemen baharu di sana. Seperti operasi yang ditetapkan, carian mengikut indeks mempunyai kerumitan algoritma O(1) . Mendapatkan elemen mengikut indeks (dapat) Mendapatkan elemen daripada LinkedList mengikut prinsip carian yang sama yang digunakan dalam operasi lain. Kerumitan bergantung pada jarak dari penghujung atau permulaan, iaitu ia berbeza dari O(1) hingga O(n/2) . Seperti yang dinyatakan sebelum ini, untuk ArrayList , mencari elemen mengikut indeks dalam tatasusunan dalaman mempunyai kerumitan O(1) . Mengalih keluar elemen mengikut indeks (alih keluar) Untuk LinkedList , prinsip yang sama digunakan sekali lagi. Pertama, elemen terletak, dan kemudian rujukan ditulis semula, jiran elemen yang dipadam kini merujuk antara satu sama lain, menghapuskan rujukan kepada elemen yang dipadam, yang kemudiannya akan dibersihkan oleh pemungut sampah. Dalam erti kata lain, kerumitan algoritma masih sama — ia berbeza dari O(1) hingga O(n/2) . Untuk ArrayList , operasi ini lebih seperti menambah elemen baharu (tambah). Mula-mula, kaedah mencari elemen yang diingini ( O(1) ), mengeluarkannya, dan kemudian semua elemen yang terletak di sebelah kanan dialihkan satu langkah ke kiri untuk menutup jurang yang dicipta oleh penyingkiran. Mengalih keluar elemen mempunyai kerumitan algoritma yang sama seperti operasi tambah — daripada O(1) hingga O(n). Semakin dekat elemen yang dialih keluar adalah ke penghujung senarai, semakin rendah kerumitan algoritma operasi ini. Dan kini kami telah merangkumi semua operasi utama. Izinkan saya mengingatkan anda bahawa apabila membandingkan kedua-dua jenis senarai ini, anda perlu menjelaskan situasi khusus yang digunakan. Hanya selepas itu anda boleh menjawab soalan penemuduga dengan jelas.

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. Meneroka soalan dan jawapan daripada temu duga kerja untuk jawatan pembangun Java.  Bahagian 10 - 3

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.
Kini kelihatan seperti tempat yang baik untuk berhenti seketika sehingga bahagian semakan seterusnya!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION