JavaRush /Java Blog /Random-ID /Kisah satu wawancara: pertanyaan menarik
GuitarFactor
Level 30
Санкт-Петербург

Kisah satu wawancara: pertanyaan menarik

Dipublikasikan di grup Random-ID
Baru-baru ini saya berkesempatan mengikuti wawancara untuk posisi magang di salah satu perusahaan IT besar. Kisah satu wawancara: pertanyaan menarik - 1Ini adalah wawancara IT pertama saya dan menurut saya ternyata menarik. Total saya “diinterogasi” selama lebih dari 3 jam (didahului dengan pekerjaan rumah dan ulangan di kantor menggunakan komputer). Saya ingin memberi penghormatan kepada pewawancara, yang tidak menyerah ketika saya menjawab pertanyaan dengan salah, namun dengan bantuan pertanyaan-pertanyaannya yang mengarahkan memaksa saya untuk berpikir dan sampai pada jawaban yang benar. Di bawah ini saya akan menyajikan beberapa “sketsa” - menurut saya, pertanyaan yang cukup menarik, beberapa di antaranya memberi saya pemahaman lebih dalam tentang aspek-aspek tertentu di Java. Mungkin hal-hal ini tampak jelas bagi sebagian orang, tetapi menurut saya akan ada orang-orang yang menganggap hal ini berguna. Di bawah frasa disorot dalam font berikut: Pewawancara - dicetak tebal Penjelasan sulih suara dan pemikiran saya - dicetak miring Jawaban saya - dalam font biasa Kita sudah selesai dengan latar belakangnya, mari kita mulai bisnis)

Sketsa 1. “Metode yang tampaknya sederhana”

Tuliskan bagaimana Anda akan menerapkan metode yang mengembalikan hasil pembagian angka a dengan angka b. Pewawancara menulis di selembar kertas
int divide(int a, int b) {
}
*Saya melirik dengan tidak percaya pada selembar kertas dengan tanda tangan metode. Apa menariknya?* Saya menulis:
int divide(int a, int b) {
    return a/b;
}
Apakah ada masalah dengan metode ini? *Saya menangkap orang bodoh yang sangat bodoh* Tampaknya tidak.. Berikutnya adalah pertanyaan yang wajar: Bagaimana jika b=0? *Wah, aku bisa dikeluarkan dari kantor ini jika terus seperti ini!* Oh iya, tentu saja. Di sini kita memiliki argumen bertipe int, sehingga Pengecualian Aritmatika akan dilempar. Jika argumennya bertipe float atau double, hasilnya adalah Infinity. Apa yang akan kita lakukan mengenai hal ini? Saya mulai menulis coba/tangkap
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*Saya dapat kembali dan membekukan: sesuatu perlu dikembalikan jika terjadi kesalahan. Namun bagaimana “sesuatu” ini bisa dibedakan dari hasil perhitungannya?* Apa yang akan kita kembalikan? Hm... Saya akan mengubah jenis variabel pengembalian menjadi Integer dan jika ada pengecualian saya akan mengembalikan nol. Bayangkan kita tidak bisa mengubah tipenya. Bisakah kita keluar? Mungkin kita bisa melakukan hal lain dengan pengecualian? *Ini dia* Kita juga bisa meneruskannya ke metode panggilan! Benar. Seperti apa tampilannya?
int divide(int a, int b) throws ArithmeticException{
    return a/b;
}

void callDivide(int a, int b) {
    try {
        divide(a, b);
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}
Apakah pengecualian itu perlu ditangani? Ya, karena kami meneruskannya secara eksplisit dari metode pembagian. (*Saya salah di sini! Berikut ini adalah pertanyaan-pertanyaan yang mengarahkan pewawancara untuk sampai pada jawaban yang benar*) Dan Pengecualian Aritmatika - jenis pengecualian apa - dicentang atau tidak? Ini adalah pengecualian Runtime, yang berarti tidak dicentang. *Inilah pertanyaan mematikannya* Jadi ternyata, menurut kata-kata Anda, jika kita menentukan throw Arithmetic Exception di tanda tangan metode, maka itu menjadi pengecualian yang dicentang? *Ugh!* Mungkin... tidak. Ya, sudah hilang. Jika kami menunjukkan lemparan /pengecualian yang tidak dicentang/ di tanda tangan, kami hanya memperingatkan bahwa metode tersebut dapat memunculkan pengecualian, tetapi tidak perlu menanganinya dalam metode pemanggilan. Itu sudah beres. Adakah hal lain yang bisa kita lakukan untuk menghindari kesalahan? *Setelah berpikir beberapa lama* Ya, kita juga dapat memeriksa apakah (b==0). Dan lakukan beberapa logika. Benar. Jadi kita bisa melakukan 3 cara:
  • coba tangkap
  • throws – meneruskan ke metode pemanggilan
  • pemeriksaan argumen
Dalam hal ini, dividemenurut Anda metode mana yang lebih disukai?
Saya akan memilih untuk meneruskan pengecualian ke metode panggilan, karena... dalam metode pembagian tidak jelas bagaimana memproses pengecualian ini dan jenis hasil apa intyang akan dikembalikan jika terjadi kesalahan. Dan dalam metode pemanggilan, saya akan menggunakan argumen b untuk memeriksa apakah sama dengan nol. Tampaknya jawaban ini memuaskan orang yang diwawancarai, tetapi sejujurnya, saya tidak yakin jawaban ini jelas))

Sketsa 2. “Siapa yang lebih cepat?”

Setelah pertanyaan standar, apa perbedaan ArrayList dari LinkedList, muncul ini: Apa yang akan terjadi lebih cepat - memasukkan elemen ke tengah ArrayListatau ke tengah LinkedList? *Di sini saya melompat, saya ingat bahwa di mana pun saya membaca sesuatu seperti “gunakan LinkedListuntuk menyisipkan atau menghapus elemen di tengah daftar.” Di rumah saya bahkan mengecek ulang kuliah JavaRush, ada ungkapan: “jika Anda akan menyisipkan (atau menghapus) banyak elemen di tengah-tengah koleksi, lebih baik Anda menggunakan LinkedList. Dalam semua kasus lainnya - ArrayList.” Dijawab otomatis* Akan lebih cepat dengan LinkedList. Tolong jelaskan
  1. Untuk menyisipkan elemen di tengah ArrayList, kita mencari elemen dalam daftar dalam waktu konstan, lalu menghitung ulang indeks elemen di sebelah kanan elemen yang disisipkan, dalam waktu linier.
  2. Untuk LinkedList.. Pertama-tama kita mencapai bagian tengah dalam waktu linier dan kemudian memasukkan elemen dalam waktu konstan, mengubah tautan untuk elemen tetangga.
Jadi ternyata mana yang lebih cepat? Hm... Ternyata sama saja. Tapi kapan LinkedListlebih cepat? Ternyata saat kita memasukkannya ke paruh pertama daftar. Misalnya, jika Anda memasukkannya di awal, Anda ArrayListharus menghitung ulang semua indeks hingga bagian paling ekor, tetapi Anda LinkedListhanya perlu mengubah referensi elemen pertama. Moral: jangan percaya secara harfiah semua yang tertulis, bahkan di JavaRush!)

Sketsa 3. “Di manakah kita tanpa persamaan dan kode hash!”

Percakapan tentang sama dengan dan kode hash sangat panjang - bagaimana cara menimpanya, apa implementasinya Object, apa yang terjadi di balik terpal, kapan sebuah elemen dimasukkan ke dalam HashMap, dll. Saya hanya akan mengutip beberapa poin yang menurut saya menarik* Bayangkan kita telah membuat sebuah kelas
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
Dan mereka tidak menimpa equalsdan hashcode. Jelaskan apa yang akan terjadi ketika kode dijalankan
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*Ada baiknya sebelum wawancara saya secara khusus menghabiskan beberapa hari untuk memahami algoritme dasar, kompleksitasnya, dan struktur datanya - ini sangat membantu, terima kasih CS50!*
  1. Buat dua instance kelas A

  2. Kami membuat peta kosong, yang secara default memiliki 16 keranjang. Kuncinya adalah objek kelas A, di mana metode equalsdan tidak ditimpa hashcode.

  3. Taruh a1di peta. Untuk melakukan ini, pertama-tama kita menghitung hashnya a1.

    Hashnya akan sama dengan apa?

    Alamat sel di memori merupakan implementasi metode dari suatu kelasObject

  4. Berdasarkan hash, kami menghitung indeks keranjang.

    Bagaimana cara menghitungnya?

    *Sayangnya, saya tidak memberikan jawaban yang jelas di sini. Anda memiliki nomor yang panjang - sebuah hash, dan ada 16 keranjang - bagaimana cara menentukan indeks sehingga objek dengan hash berbeda didistribusikan secara merata ke seluruh keranjang? Saya dapat membayangkan indeks dihitung seperti ini:

    int index = hash % buckets.length

    Sudah di rumah saya melihat bahwa implementasi asli dalam kode sumber sedikit berbeda:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. Kami memeriksa bahwa tidak ada tabrakan dan memasukkan a1.

  6. Mari beralih ke metodenya get. Instance a1 dan a2 dijamin memiliki perbedaan hash(alamat berbeda di memori), jadi kami tidak akan menemukan apa pun untuk kunci ini

    Bagaimana jika kita mendefinisikan ulang hanya hashcodedi kelas A dan mencoba memasukkan ke dalam peta hash terlebih dahulu sepasang dengan kunci a1, dan kemudian dengan a2?

    Kemudian pertama-tama kita akan menemukan keranjang yang diinginkan hashcode- operasi ini akan dilakukan dengan benar. Selanjutnya, mari kita mulai menelusuri objek-objek Entrydi LinkedList yang dilampirkan ke keranjang dan membandingkan kuncinya dengan equals. Karena equalstidak ditimpa, maka implementasi dasar diambil dari kelas Object- perbandingan dengan referensi. a1 dan a2 dijamin memiliki link yang berbeda, jadi kita akan “kehilangan” elemen a1 yang disisipkan, dan a2 akan ditempatkan di LinkedList sebagai node baru.

    Apa kesimpulannya? Apakah mungkin untuk menggunakannya sebagai kunci dalam HashMapsuatu objek dengan non-override equalshashcode?

    Tidak Anda tidak bisa.

Sketsa 4. “Ayo kita hancurkan dengan sengaja!”

Setelah pertanyaan tentang Kesalahan dan Pengecualian, pertanyaan berikut diikuti: Tulis contoh sederhana di mana suatu fungsi akan menampilkan StackOverflow. *Kemudian saya ingat bagaimana kesalahan ini mengganggu saya ketika saya mencoba menulis beberapa fungsi rekursif* Ini mungkin akan terjadi dalam kasus panggilan rekursif, jika kondisi untuk keluar dari rekursi tidak ditentukan dengan benar. *Lalu saya mulai sedikit pandai, akhirnya pewawancara membantu, semuanya menjadi sederhana*
void sof() {
    sof();
}
Apa bedanya kesalahan ini dengan OutOfMemory? *Saya tidak menjawab di sini, baru kemudian saya menyadari bahwa ini adalah pertanyaan tentang pengetahuan Stackmemori HeapJava (panggilan dan referensi ke objek disimpan di Stack, dan objek itu sendiri disimpan di memori Heap). Oleh karena itu, StackOverflow dibuang ketika tidak ada lagi ruang di Stackmemori untuk pemanggilan metode berikutnya, dan OutOfMemoryruang untuk objek telah habis di Heapmemori*
Inilah momen-momen wawancara yang saya ingat. Pada akhirnya, saya diterima untuk magang, jadi saya memiliki 2,5 bulan pelatihan di depan saya dan, jika semuanya berjalan dengan baik, pekerjaan di perusahaan) Jika ada minat, saya bisa menulis artikel lain, kali ini lebih kecil, dengan analisis masalah sederhana namun ilustratif yang diberikan kepada saya saat diwawancarai di perusahaan lain. Sekian dari saya, semoga artikel ini dapat membantu seseorang memperdalam atau mengorganisasikan ilmunya. Selamat belajar semuanya!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION