Odnoklassniki parsing di Joker 2019



Dari tanggal 28 hingga 29 Oktober, Joker 2019 diadakan di St. Petersburg - konferensi terbesar dan paling keras di luasnya Rusia yang didedikasikan untuk pembangunan Jawa. Acara ini diadakan untuk ketujuh kalinya dan, seperti biasa, memecahkan rekor kehadiran, kali ini acara tersebut menarik lebih dari 2.000 spesialis.

Teman sekelas secara tradisional mengambil bagian dalam Joker sebagai mitra acara. Tahun ini, di stan kami, seseorang dapat mencoba untuk mengatasi tugas-tugas "tidak terpecahkan" yang terkenal dari para insinyur OK.RU terkemuka. Peserta konferensi yang menjawab pertanyaan dengan benar menerima hadiah.

Dalam keadilan, saya harus mengatakan bahwa dari 1.000 selebaran dengan tugas yang kami bagikan, kurang dari 100 dikembalikan. Yang terbaik adalah solusi, yang mencetak 4,5 poin dari 5.

Kami menerbitkan tugas dan solusinya sehingga Anda dapat menguji kekuatan Anda.

1. Enum yang heroik


Kode sumber untuk gim yang kurang dikenal mengungkapkan kode tersebut. Apa implementasi Group.of buruk, dan bagaimana cara memperbaikinya?

 enum Group { Few(1, 4), Several(5, 9), Pack(10, 19), Lots(20, 49), Swarm(50, Integer.MAX_VALUE); Group(int min, int max) { ... } public static Group of(int count) { for (Group group : Group.values()) { if (count >= group.min && count <= group.max) { return group; } } throw new IllegalArgumentException(); } } 

Solusi
Jika Anda tidak berbicara tentang gaya pengkodean, fragmen ini memiliki kelemahan objektif - masalah kinerja potensial. Meskipun pencarian linear sering ternyata menjadi hambatan, dalam hal ini bukan itu masalahnya, karena enum ini hanya memiliki lima elemen. Dan yang benar-benar dapat memengaruhi kinerja secara negatif adalah alokasi memori yang berlebihan saat memanggil Group.values() . Masalahnya adalah bahwa values() metode enum setiap kali mengembalikan salinan baru array, dan HotSpot belum dapat mengoptimalkannya. Solusi sederhana adalah membuat salinan array values() Anda sendiri dan mengulanginya:

 private static final Group[] ALL_GROUPS = Group.values(); public static Group of(int count) { for (Group group : ALL_GROUPS) { .... } 


2. Mimpi


Java 13 telah dirilis, dan Nikolai masih hanya memahami stream. Tunjukkan kesalahan dalam metode yang menghitung perbedaan antara elemen aliran maksimum dan minimum.

 int getDiameter(Stream<Integer> stream) { int min = stream.min(Integer::compare).get(); int max = stream.max(Integer::compare).get(); return max - min; } 

Solusi
Streaming di Jawa biasanya satu kali: memanggil operasi terminal kedua (dalam hal ini, max ) akan gagal:

 java.lang.IllegalStateException: stream has already been operated upon or closed 

Selain itu, min dan max mengembalikan Optional , operasi get() yang akan melempar NoSuchElementException untuk aliran kosong. Oleh karena itu, lebih tepat untuk memeriksa isPresent() sebelum memanggil get() atau menggunakan metode Optional lainnya: orElse , atauElseThrow , dll.

Akhirnya, fakta bahwa perbedaan antara kedua int tidak dapat lagi masuk ke int tidak akan lepas dari pengembang yang cermat, dan akan sangat berguna untuk mengubah jenis nilai pengembalian menjadi long .

3. Buffer aman


ByteBuffer primitif sinkronisasi Java yang dapat membuat put dan get operasi thread aman pada ByteBuffer generik?

 final ByteBuffer buf = ByteBuffer.allocate(SIZE); int get(int offset) { return buf.get(offset); } void put(int offset, int value) { buf.putInt(offset, value); } 

Pilih opsi yang paling efisien jika Anda tahu bahwa ada banyak utas, dan jalankan lebih sering daripada put.

  • disinkronkan
  • Reentrantlock
  • ReentrantReadWriteLock
  • Stampedlock
  • Semaphore
  • Membaca dan menulis di Jawa selalu bersifat atom

Solusi
ReentrantReadWriteLock memohon untuk ReentrantReadWriteLock pembaca dan penulis, dan seringkali ini akan menjadi solusi yang efektif. Tetapi perhatikan bahwa dalam kasus ini, operasi get and put sangat sederhana - probabilitas bahwa put kompetitif dapat mengganggu get adalah kecil, apalagi, kondisi put lebih kecil kemungkinannya terjadi dengan operasi put. Jadi, Anda dapat menerapkan mekanisme penguncian optimis yang diberikan StampedLock .

StampedLock akan lebih efisien daripada ReentrantReadWriteLock karena fakta bahwa dalam kasus keberhasilan jalur cepat yang optimis, variabel bersama tidak diperbarui sama sekali, sementara ReentrantReadWriteLock melakukan setidaknya satu CAS terbaik.

4. Hadiah


Ilya sedang mengembangkan showcase hadiah di jejaring sosial. Bantu dia menulis metode add untuk struktur yang tidak lebih dari N dari hadiah terbaru. Hadiah tidak boleh ditambahkan jika sudah ada, atau jika itu lebih tua dari sisa N.

 interface Present { long getId(); Date getCreated(); } void add(Present p) { // Implement me } 

Solusi
TreeSet atau PriorityQueue secara alami cocok sebagai struktur data untuk secara efektif menambahkan hadiah dan menghapus yang terlama tidak lebih buruk daripada untuk O (log N). Semua trik hanya ada di pembanding: tidak cukup membandingkan hadiah hanya dengan getCreated() , karena tanggal pembuatan tidak harus unik. Oleh karena itu, Anda perlu membandingkan dulu dengan getCreated() , lalu dengan getId() . Komparator seperti itu akan memastikan keunikan elemen dan pemesanan berdasarkan tanggal.

 TreeSet<Present> tree = new TreeSet<>( Comparator.comparing(Present::getCreated) .thenComparing(Present::getId)); 

Tetap menjadi masalah kecil: saat menambahkan hadiah, pastikan ukurannya tidak melebihi N, dan jika perlu, hapus elemen koleksi yang pertama, terlama.

 void add(Present p) { if (tree.add(p) && tree.size() > N) { tree.pollFirst(); } } 


5. Anda tidak akan menunggu


Mengapa Julia tidak akan pernah menunggu akhir dari program ini?

 var executor = Executors.newFixedThreadPool(4); for (File f : File.listRoots()) { executor.submit(() -> f.delete()); } executor.awaitTermination(2, TimeUnit.HOURS); 

Solusi
Dokumentasi awaitTermination menunjukkan bahwa permintaan shutdown harus mendahului eksekusi. Sederhana: Julia lupa memanggil executor.shutdown () .

Source: https://habr.com/ru/post/id474502/


All Articles