Java Practical Tasks - untuk kursus dan kegiatan lainnya
Beberapa kata pengantar
Selama beberapa tahun terakhir, saya telah mengajar pemrograman Java. Seiring waktu, itu berubah - kadang-kadang bagian yang berbeda ditambahkan atau dibuang, urutan topik berubah, pendekatan untuk membangun rencana kelas itu sendiri berubah, dan sebagainya. Artinya, kursus telah ditingkatkan. Salah satu masalah utama yang dihadapi dalam mempersiapkan kursus adalah tugas. Tentang mereka dan akan dibahas.
Faktanya adalah bahwa setiap kelas saya terdiri dari dua bagian. Pada awalnya, saya bertindak sebagai dosen - saya memberi tahu Anda dengan contoh kode tentang beberapa topik baru (kelas, warisan, obat generik, dan sebagainya). Bagian kedua praktis. Jelas, tidak masuk akal untuk hanya berbicara tentang pemrograman, Anda perlu memprogram. Prioritas di kelas adalah pemecahan masalah, yaitu memprogram sesuatu. Pemrograman di kelas berbeda dari pemrograman di rumah, seperti di kelas Anda dapat mengajukan pertanyaan, menunjukkan kode, mendapatkan penilaian cepat dari kode, komentar tentang peningkatan, koreksi tulisan. Sangat mudah untuk menemukan tugas untuk pelajaran pertama. Tugas untuk loop, pernyataan kondisional, dan OOP (misalnya, tulis kelas "Dog" atau kelas "Vector"). Layanan seperti
leetcode bahkan memungkinkan Anda untuk memverifikasi kebenaran penyelesaian masalah seperti itu, secara online. Tapi tugas apa yang harus diberikan siswa dalam pelajaran yang didedikasikan untuk koleksi? Stream? Bagaimana dengan anotasi? Selama beberapa tahun, saya membuat atau merevisi beberapa tugas seperti itu, dan artikel ini, pada kenyataannya, adalah kumpulan dari masalah-masalah ini (solusi dilampirkan ke beberapa masalah).
Tentu saja, semua tugas sudah muncul di suatu tempat. Namun, artikel ini ditujukan untuk guru kursus pemrograman (untuk bahasa yang mirip dengan Jawa, sebagian besar tugas akan dilakukan), atau mereka yang mengajar pemrograman secara pribadi. Tugas-tugas ini dapat digunakan "di luar kotak" di kelas Anda. Pembelajar Java juga dapat mencoba menyelesaikannya. Tetapi keputusan semacam itu membutuhkan verifikasi dan evaluasi pihak ketiga.
Beberapa tugas paling sederhana yang telah digunakan semua orang selama beberapa dekade, saya juga termasuk dalam artikel ini. Mungkin, agar tidak segera memulai dengan kelas abstrak.
Setiap ide dan saran dipersilahkan!
Daftar tugas
Dasar-dasarnya
1.0. Maksimum, Minimum, dan Rata-Rata1.1 Sortir Array1.2 Menemukan bilangan prima1.3 Menghapus dari suatu arrayDasar-Dasar OOP
2.0 Merancang dan membuat kelas yang menggambarkan vektor2.1 Menghasilkan elemen acak dengan bobot2.2 Daftar TertautRekursi
3.0 Pencarian Biner3.1 Temukan akar persamaan3.2 Pohon Pencarian BinerWarisan
4.0 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi4.1 Menerapkan hierarki kelas yang menggambarkan angka tiga dimensi - 24.2 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 34.3 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 4Garis
5.0 Kamus Frekuensi SuratKelas dan antarmuka abstrak
6.0 Konverter suhu6.1. Stringbuilder dengan dukungan undo6.2. Statebuilding Stringbuilder (pola pengamat)6.4. Mengisi array dengan FunctionKoleksi
7.0 Kamus Frekuensi Kata7.1. Koleksi tanpa duplikat7.2. ArrayList dan LinkedList7.3. Tulis iterator di atas sebuah array7.4. Tulis iterator pada array dua dimensi7.5. Iterator yang bahkan lebih kompleks7.6. Iterator melalui dua iterator7.7. Menghitung Elemen7.8. Ubah kunci dan nilai dalam PetaMultithreading
8.0 Serikat8.1. Sinkronisasi utas8.2. Pabrikan KonsumenAnotasi
9.0. Anotasi khusus - pembuatan dan penggunaan dengan refleksi10.0 Jumlah batasan jalan10.1. Pencarian Wikipedia. Dalam program konsol10.2. Tugas akhir - utilitas konsol untuk mengunduh file melalui HTTP10.3. Tugas akhir - cuaca Telegram-bot10.4. Tugas akhir - pengenalan tulisan tanganDasar-dasarnya
1.0. Maksimum, Minimum, dan Rata-Rata
Tantangan:Isi array dengan angka acak dan cetak nilai maksimum, minimum dan rata-rata.
Untuk menghasilkan angka acak, gunakan metode
Math.random () , yang mengembalikan nilai dalam interval [0, 1].
Solusi:public static void main(String[] args) { int n = 100; double[] array = new double[n]; for (int i = 0; i < array.length; i++) { array[i] = Math.random(); } double max = array[0];
1.1. Menerapkan algoritma semacam gelembung untuk mengurutkan array
Solusi: for (int i = 0; i < array.length; i++) { for (int j = 0; j < array.length - i - 1; j++) { if (array[j] > array[j + 1]) { double temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } } for (int i = 0; i < array.length; i++) { System.out.println(array[i]); }
1.2. Cari bilangan prima
Tantangan:Tulis program yang mencetak bilangan prima ke konsol antara [2, 100].
Gunakan
% operator (sisa divisi) dan loop untuk menyelesaikan masalah ini.
Solusi: for(int i = 2; i <= 100; i ++){ boolean isPrime = true; for(int j = 2; j < i; j++){ if(i % j == 0){ isPrime = false; break; } } if(isPrime){ System.out.println(i); } }
Atau menggunakan
label loop :
out_for: for (int i = 2; i <= 100; i++) { for (int j = 2; j < i; j++) { if (i % j == 0) { continue out_for; } } System.out.println(i); }
1.3. Hapus dari array
Tantangan:Diberikan array bilangan bulat dan bilangan bulat lainnya. Hapus semua kemunculan angka ini dari array (seharusnya tidak ada celah).
Solusi: public static void main(String[] args) { int test_array[] = {0,1,2,2,3,0,4,2}; System.out.println(Arrays.toString(removeElement(test_array, 3))); } public static int[] removeElement(int[] nums, int val) { int offset = 0; for(int i = 0; i< nums.length; i++){ if(nums[i] == val){ offset++; } else{ nums[i - offset] = nums[i]; } }
Anda dapat menulis sendiri metode untuk memotong ekor array, tetapi perlu dicatat bahwa metode standar akan bekerja lebih cepat:
public static int[] removeElement(int[] nums, int val) { int offset = 0; for(int i = 0; i< nums.length; i++){ if(nums[i] == val){ offset++; } else{ nums[i - offset] = nums[i]; } } int[] newArray = new int[nums.length - offset]; for(int i = 0; i < newArray.length; i++){ newArray[i] = nums[i]; } return newArray; }
Namun, jika Anda pergi dengan cara ini, pertama-tama Anda dapat membuat array dengan panjang yang diinginkan, dan kemudian mengisinya:
public static int[] removeElement(int[] nums, int val) { int count = 0;
2.0. Merancang dan membuat kelas vektor
Tantangan:Buat kelas yang menggambarkan vektor (dalam ruang tiga dimensi).
Ia harus memiliki:
Jika metode mengembalikan vektor, maka harus mengembalikan objek baru, dan tidak mengubah basis. Artinya, Anda perlu menerapkan templat "
Objek Tidak Berubah "
Solusi: public class Vector {
Anda dapat menggunakan kelas ini seperti ini:
public static void main(String[] args) { Vector[] vectors = Vector.generate(10); System.out.println(vectors[0]); System.out.println(vectors[1]); System.out.println(vectors[0].length()); System.out.println(vectors[0].scalarProduct(vectors[1])); System.out.println(vectors[0].crossProduct(vectors[1])); System.out.println(vectors[0].cos(vectors[1])); System.out.println(vectors[0].add(vectors[1])); System.out.println(vectors[0].subtract(vectors[1])); }
Anda dapat menggeneralisasi solusi ini dan menulis kelas Vector untuk dimensi yang berubah-ubah:
public class Vector {
2.1. Menghasilkan item acak dengan berat
Tantangan:Tulis kelas yang konstruktornya mengambil dua array: array nilai dan array bobot nilai.
Kelas harus berisi metode yang akan mengembalikan elemen dari array pertama secara acak, dengan mempertimbangkan bobotnya.
Contoh:
Array diberikan [1, 2, 3], dan array bobot [1, 2, 10].
Rata-rata, nilai
"1" harus kembali 2 kali lebih kecil dari nilai
"2" dan sepuluh kali lebih jarang dari nilai
"3" .
Solusi: class RandomFromArray { private int[] values;
Tapi, karena array
rentang diurutkan, Anda bisa (dan harus) menggunakan pencarian biner:
public int getRandom() { int random = (int) (Math.random() * (sum - 1)); int index = Arrays.binarySearch(ranges, random); return values[index >= 0 ? index : -index - 2]; }
Ada solusi lain untuk masalah ini. Anda bisa membuat larik yang ukurannya sama dengan jumlah semua bobot. Kemudian pilihan elemen acak turun untuk menghasilkan indeks acak. Yaitu, jika array nilai diberikan [1, 2, 3], dan array bobot [1, 2, 10], maka Anda dapat segera membuat array [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] dan ekstrak elemen acak darinya:
class RandomFromArray { private int[] extended_values;
Solusi ini memiliki keuntungan - waktu untuk mengekstrak elemen acak
O (1) , berbeda dengan log (n) dalam solusi sebelumnya. Namun, itu membutuhkan banyak memori:
O( jumlahn)
2.2. Daftar tertaut
Tugas lain yang sering saya berikan adalah implementasi daftar tertaut. Itu dapat diberikan dalam bentuk yang paling sederhana (implement
add () dan
get () saja ), atau Anda dapat meminta untuk mengimplementasikan
java.util.List .
Saya tidak akan membahas hal ini secara rinci, ada banyak artikel tentang implementasi daftar tertaut di Jawa di Habr, misalnya yang ini:
Struktur data dalam gambar. LinkedListTantangan:Tulis metode yang memeriksa apakah elemen yang diberikan ada dalam array atau tidak.
Gunakan enumerasi dan pencarian biner untuk menyelesaikan masalah ini.
Bandingkan runtime dari kedua solusi untuk array besar (mis. 100000000 elemen)
Solusi: public static int bruteForce(double[] array, double key) { for (int i = 0; i < array.length; i++) { if (array[i] == key) return i; } return -1; } public static int binarySearchRecursively(double[] sortedArray, double key) { return binarySearchRecursively(sortedArray, key, 0, sortedArray.length); } private static int binarySearchRecursively (double[] sortedArray, double key, int low, int high) { int middle = (low + high) / 2;
3.1. Temukan akar persamaannya
Tantangan:Temukan akar persamaannya
c o s ( x 5 ) + x 4 - 345,3 ∗ x - 23 = 0
di segmen [0; 10] dengan akurasi
x tidak lebih buruk dari 0,001. Diketahui bahwa root unik dalam interval ini.
Gunakan
metode membagi dua (dan rekursi) untuk ini.
Solusi:
Catatan: jika kita ingin mencapai akurasi yang diperlukan bukan dalam
x , di
y , maka kondisi dalam metode harus ditulis ulang:
if(Math.abs(func(start)- func(end)) <= 0.001){ return start; }
Trik kecil: mengingat bahwa himpunan nilai ganda adalah terbatas (ada dua nilai yang berdekatan di antaranya tidak ada nilai ganda), tulis ulang kondisi untuk keluar dari rekursi sebagai berikut:
double x = start + (end - start) / 2; if(x == end || x == start){ return x; }
Dengan demikian, kami memperoleh akurasi maksimum yang umumnya dapat diperoleh dengan menggunakan pendekatan ini.
3.2. Pohon pencarian biner
Menerapkan
pohon pencarian biner adalah tugas yang sangat baik. Saya biasanya memberikannya saat rekursi.
Saya tidak akan menulis banyak tentang ini, ada banyak artikel / implementasi yang sangat berbeda:
Struktur data: pohon biner.Pohon biner, implementasi cepatImplementasi Java dari pohon biner hashWarisan
4.0 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi
Tantangan:Menerapkan hierarki kelas:

Kelas
Box adalah wadah, dapat berisi bentuk lain. Metode
add () mengambil Shape sebagai input. Kita perlu menambahkan bentuk baru sampai kita mengambil ruang untuk mereka di dalam Kotak (kita hanya akan mempertimbangkan volume, mengabaikan bentuk. Misalkan kita menuangkan cairan). Jika tidak ada cukup ruang untuk menambahkan bentuk baru, maka metode tersebut harus mengembalikan
false .
Solusi: class Shape { private double volume; public Shape(double volume) { this.volume = volume; } public double getVolume() { return volume; } } class SolidOfRevolution extends Shape { private double radius; public SolidOfRevolution(double volume, double radius) { super(volume); this.radius = radius; } public double getRadius() { return radius; } } class Ball extends SolidOfRevolution {
Agar tidak kembali ke tugas ini, beberapa variasi tugas ini dijelaskan di bawah ini.
4.1. Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 2
Tantangan:Terapkan hierarki kelas yang sama, tetapi buat beberapa kelas abstrak.
Solusi: abstract class Shape { public abstract double getVolume(); } abstract class SolidOfRevolution extends Shape { protected double radius; public SolidOfRevolution(double radius) { this.radius = radius; } public double getRadius() { return radius; } } class Ball extends SolidOfRevolution {
4.2. Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 3
Tantangan:Menerapkan hierarki kelas yang sama, tetapi menggunakan antarmuka.
Selain itu, siswa didorong untuk mengimplementasikan antarmuka
Sebanding .
Solusi: interface Shape extends Comparable<Shape>{ double getVolume(); @Override default int compareTo(Shape other) { return Double.compare(getVolume(), other.getVolume()); } } abstract class SolidOfRevolution implements Shape { protected double radius; public SolidOfRevolution(double radius) { this.radius = radius; } public double getRadius() { return radius; } } class Ball extends SolidOfRevolution {
4.3. Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 4
Tantangan:Tambahkan bentuk rotasi ke hierarki kelas untuk fungsi arbitrer. Anda dapat menghitung perkiraan volume menggunakan integral tertentu. Karena volume angka rotasi di sekitar sumbu
x adalah
V x = p i i n t b a f 2 ( x ) d x
Dan integralnya adalah
Anda dapat menulis implementasi
metode persegi panjang :
class SolidRevolutionForFunction extends SolidOfRevolution { private Function<Double, Double> function; private double a; private double b; public SolidRevolutionForFunction( Function<Double, Double> function, double a, double b) { super(b - a); this.function = function; this.a = a; this.b = b; } @Override public double getVolume() { double sum = 0; int iterations = 10000; double delta = (b - a)/iterations; for(int i = 0; i < iterations; i++){ double x = a + ((b - a) * i/iterations); sum += Math.pow(function.apply(x), 2) * delta; } return Math.PI * sum; } }
public static void main(String[] args) { Shape shape = new SolidRevolutionForFunction(new Function<Double, Double>() { @Override public Double apply(Double x) { return Math.cos(x); } }, 0, 10); System.out.println(shape.getVolume()); }
Tentu saja, kami tidak memperhitungkan keakuratan perhitungan di sini, dan kami tidak memilih jumlah partisi untuk mencapai akurasi yang diperlukan, tetapi ini adalah tugas pemrograman, bukan metode numerik, jadi kami menghilangkan ini di ruang kelas.
Garis
Anda dapat menemukan banyak tugas per baris. Saya biasanya memberikan ini:
- Tulis metode untuk menemukan string terpanjang dalam array.
- Tulis metode yang memeriksa apakah sebuah kata adalah palindrom .
- Tulis metode yang menggantikan dalam teks semua kemunculan kata
Massal "byaka" dengan "[cut out
disensor]. " - Ada dua garis. Tulis metode yang mengembalikan jumlah kemunculan satu baris di baris lain.
Saya tidak akan menjelaskan solusi untuk masalah seperti itu, dan ada sejumlah besar tugas untuk string juga.
Yang lebih menarik, saya suka yang ini:
5.0. Kamus frekuensi huruf alfabet Rusia (atau Inggris).
Tantangan:Buat kamus frekuensi huruf alfabet Rusia (atau Inggris). Kami menghilangkan masalah memilih dan menganalisis tubuh bahasa, itu akan cukup untuk mengambil teks pendek).
Solusi: void buildDictionaryWithMap(String text){ text = text.toLowerCase(); Map<Character, Integer> map = new HashMap<>(); for(int i = 0; i < text.length(); i++){ char ch = text.charAt(i);
Atau lebih:
void buildDictionary(String text){ text = text.toLowerCase(); int[] result = new int['' - '' + 1]; for(int i = 0; i < text.length(); i++){ char ch = text.charAt(i); if(ch >= '' && ch <= ''){ result[ch - '']++; } } for(int i = 0; i < result.length; i++){ System.out.println((char) (i + '') + " = " + result[i]); } }
Kelas dan antarmuka abstrak
6.0 Konverter suhu
Tantangan:Tulis kelas BaseConverter untuk mengkonversi dari derajat
Celcius ke
Kelvin ,
Fahrenheit , dan sebagainya. Metode harus memiliki metode
konversi , yang
dan apakah konversi.
Solusi: interface Converter { double getConvertedValue(double baseValue); } class CelsiusConverter implements Converter { @Override public double getConvertedValue(double baseValue) { return baseValue; } } class KelvinConverter implements Converter { @Override public double getConvertedValue(double baseValue) { return baseValue + 273.15; } } class FahrenheitConverter implements Converter { @Override public double getConvertedValue(double baseValue) { return 1.8 * baseValue + 32; } } public class Main { public static void main(String[] args) { double temperature = 23.5; System.out.println("t = " + new CelsiusConverter().getConvertedValue(temperature)); System.out.println("t = " + new KelvinConverter().getConvertedValue(temperature)); System.out.println("t = " + new FahrenheitConverter().getConvertedValue(temperature)); } }
Selain itu, Anda dapat meminta untuk menerapkan metode pabrik , seperti ini: interface Converter { double getConvertedValue(double baseValue); public static Converter getInstance(){ Locale locale = Locale.getDefault(); String[] fahrenheitCountries = {"BS", "US", "BZ", "KY", "PW"}; boolean isFahrenheitCountry = Arrays.asList(fahrenheitCountries).contains(locale.getCountry()); if(isFahrenheitCountry){ return new FahrenheitConverter(); } else { return new CelsiusConverter(); } } }
6.1. Stringbuilder dengan dukungan undo
Tugas:Tulis kelas StringBuilder Anda dengan dukungan untuk operasi undo . Untuk melakukan ini, delegasikan semua metode ke StringBuilder standar , dan di kelas Anda sendiri simpan daftar semua operasi untuk undo () untuk dieksekusi . Ini akan menjadi implementasi templat Tim .Solusi: class UndoableStringBuilder { private interface Action{ void undo(); } private class DeleteAction implements Action{ private int size; public DeleteAction(int size) { this.size = size; } public void undo(){ stringBuilder.delete( stringBuilder.length() - size, stringBuilder.length()); } } private StringBuilder stringBuilder;
6.2. Statebuilding Stringbuilder (pola pengamat)
Tugas:Tulis kelas StringBuilder Anda, dengan kemampuan untuk memberi tahu objek lain tentang perubahan di negaranya. Untuk melakukan ini, delegasikan semua metode ke StringBuilder standar , dan terapkan pola desain Observer di kelas Anda sendiri .Solusi: interface OnStringBuilderChangeListener { void onChange(OvservableStringBuilder stringBuilder); } class OvservableStringBuilder {
6.3. Saring
Soal:Menulis Cara penyaring , yang menerima array input (dari jenis apa pun), dan implementasi antarmuka Filter metode c berlaku (Object o) , untuk menghapus dari array berlebihanPeriksa cara kerjanya pada string atau objek lain.Solusi:Biasanya, saya memberikan tugas ini sebelum Generik, sehingga siswa menulis metode tanpa mereka menggunakan Object: interface Filter { boolean apply(Object o); } public class Main { public static Object[] filter(Object[] array, Filter filter) { int offset = 0; for(int i = 0; i< array.length; i++){ if(!filter.apply(array[i])){ offset++; } else{ array[i - offset] = array[i]; } }
Tapi, itu mungkin dengan Generics. Kemudian Anda dapat menggunakan Fungsi standar : public class Main { public static <T> T[] filter(T[] array, Function<? super T, Boolean> filter) { int offset = 0; for (int i = 0; i < array.length; i++) { if (!filter.apply(array[i])) { offset++; } else { array[i - offset] = array[i]; } }
6.4. Mengisi array
Tugas yang agak mirip dengan yang sebelumnya:Tulis metode isian yang menerima larik objek dan implementasi antarmuka Fungsi (atau milik Anda).Metode pengisian harus mengisi array, mendapatkan nilai baru dengan indeks menggunakan implementasi antarmuka Fungsi. Artinya, Anda ingin menggunakannya seperti ini: public static void main(String[] args) { Integer[] squares = new Integer[100]; fill(squares, integer -> integer * integer);
Solusi: public static <T> void fill(T[] objects, Function<Integer, ? extends T> function) { for(int i = 0; i < objects.length; i++){ objects[i] = function.apply(i); } }
Koleksi
7.0 Kamus Frekuensi Kata
lihat Masalah tentang kamus frekuensi huruf alfabet7.1. Koleksi tanpa duplikat
Tugas:Tulis metode yang menerima koleksi objek sebagai input, dan mengembalikan koleksi tanpa duplikat.Solusi: public static <T> Collection<T> removeDuplicates(Collection<T> collection) { return new HashSet<>(collection);
7.2. ArrayList dan LinkedList
Tulis metode yang menambahkan 1.000.000 elemen ke ArrayList dan LinkedList. Tulis metode lain yang memilih elemen secara acak 100.000 kali dari daftar yang terisi. Ukur waktu yang dihabiskan untuk itu. Bandingkan hasilnya dan sarankan mengapa demikian.Solusi: public static void compare2Lists() { ArrayList<Double> arrayList = new ArrayList<>(); LinkedList<Double> linkedList = new LinkedList<>(); final int N = 1000000; final int M = 1000; for (int i = 0; i < N; i++) { arrayList.add(Math.random()); linkedList.add(Math.random()); } long startTime = System.currentTimeMillis(); for (int i = 0; i < M; i++) { arrayList.get((int) (Math.random() * (N - 1))); } System.out.println(System.currentTimeMillis() - startTime); startTime = System.currentTimeMillis(); for (int i = 0; i < M; i++) { linkedList.get((int) (Math.random() * (N - 1))); } System.out.println(System.currentTimeMillis() - startTime); }
7.3. Tulis iterator di atas sebuah array
Solusi: class ArrayIterator<T> implements Iterator<T>{ private T[] array; private int index = 0; public ArrayIterator(T[] array) { this.array = array; } @Override public boolean hasNext() { return index < array.length; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); return array[index++]; } }
7.4. Iterator array dua dimensi
Tugas:Tuliskan iterator pada array dua dimensi.Solusi: class Array2d<T> implements Iterable<T>{ private T[][] array; public Array2d(T[][] array) { this.array = array; } @Override public Iterator<T> iterator() { return new Iterator<T>() { private int i, j; @Override public boolean hasNext() { for(int i = this.i; i< array.length; i++){ for(int j = this.j; j< array[i].length; j++){ return true; } } return false; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); T t = array[i][j]; j++; for(int i = this.i; i< array.length; i++){ for(int j = (i == this.i ? this.j : 0); j< array[i].length; j++){ this.i = i; this.j = j; return t; } } return t; } }; } }
7.5. Iterator yang bahkan lebih kompleks
Saya suka tugas ini. Dia menjangkau hanya beberapa siswa dalam kelompok yang relatif mudah untuk mengatasi tugas-tugas sebelumnya.Tugas:Dan iterator. Metode () berikutnya mengembalikan String atau iterator dari struktur yang sama (yaitu, yang mengembalikan String atau iterator yang sama). Tulis di atas iterator ini yang lain, yang sudah “rata”Solusi di tumpukan: public class DeepIterator implements Iterator<String> { private Stack<Iterator> iterators; private String next; private boolean hasNext; public DeepIterator(Iterator<?> iterator) { this.iterators = new Stack<Iterator>(); iterators.push(iterator); updateNext(); } @Override public boolean hasNext() { return hasNext; } private void updateNext(){ if(iterators.empty()){ next = null; hasNext = false; return; } Iterator current = iterators.peek(); if (current.hasNext()) { Object o = current.next(); if (o instanceof String) { next = (String) o; hasNext = true; } else if (o instanceof Iterator) { Iterator iterator = (Iterator) o; iterators.push(iterator); updateNext(); } else { throw new IllegalArgumentException(); } } else { iterators.pop(); updateNext(); } } @Override public String next() throws NoSuchElementException { if(!hasNext){ throw new NoSuchElementException(); } String nextToReturn = next; updateNext(); return nextToReturn; } @Override public void remove() { throw new UnsupportedOperationException(); } }
Solusi rekursif: class DeepIterator implements Iterator<String> { private Iterator subIter; private DeepIterator newIter; public DeepIterator(Iterator iniIter) { this.subIter = iniIter; } @Override public boolean hasNext() { if (subIter.hasNext()) return true; if (newIter != null) return newIter.hasNext(); return false; } @Override public String next() { if(!hasNext()) throw new NoSuchElementException(); Object obj = null; if (newIter != null && newIter.hasNext()) obj = newIter.next(); if (subIter.hasNext() && obj == null) { obj = subIter.next(); if (obj instanceof Iterator && ((Iterator) obj).hasNext()) { newIter = new DeepIterator((Iterator) obj); } } if(obj instanceof Iterator){ obj = next(); } return (String) obj; } }
7.6. Iterator melalui dua iterator
Tugas:Tuliskan iterator yang melewati dua iterator.Solusi: class ConcatIterator<T> implements Iterator<T> { private Iterator<T> innerIterator1; private Iterator<T> innerIterator2; public ConcatIterator (Iterator<T> innerIterator1, Iterator<T> innerIterator2) { this.innerIterator1 = innerIterator1; this.innerIterator2 = innerIterator2; } @Override public boolean hasNext() { while (innerIterator1.hasNext()) return true; while (innerIterator2.hasNext()) return true; return false; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); while (innerIterator1.hasNext()) return innerIterator1.next(); while (innerIterator2.hasNext()) return innerIterator2.next(); return null; } }
7.7. Menghitung Elemen
Tulis metode yang menerima array input elemen tipe K (Generik) dan mengembalikan Peta <K, Integer>, di mana K adalah nilai dari array, dan Integer adalah jumlah entri dalam array.Artinya, tanda tangan metode terlihat seperti ini: <K> Map<K, Integer> arrayToMap(K[] ks);
Solusi: public static <K> Map<K, Integer> countValues(K[] ks) { Map<K, Integer> map = new HashMap<>(); for (K k : ks) { map.compute(k, new BiFunction<K, Integer, Integer>() { @Override public Integer apply(K k, Integer count) { return count == null ? 1 : count + 1; } }); } return map; }
7.8. Ubah kunci dan nilai dalam Peta
Tulis metode yang menerima Peta <K, V> dan mengembalikan Peta, di mana kunci dan nilai dibalik. Karena nilainya bisa bertepatan, tipe nilai dalam Peta tidak akan lagi menjadi K , tetapi Koleksi <K>:
Map<V, Collection<K>>
Solusi: public static <K, V> Map<V, Collection<K>> inverse(Map<? extends K, ? extends V> map){ Map<V, Collection<K>> resultMap = new HashMap<>(); Set<K> keys = map.keySet(); for(K key : keys){ V value = map.get(key); resultMap.compute(value, (v, ks) -> { if(ks == null){ ks = new HashSet<>(); } ks.add(key); return ks; }); } return resultMap; }
Multithreading
8.0 Serikat
Tugas:Cetak status aliran sebelum dimulai, setelah dimulai, dan saat runtime.Solusi: Thread thread = new Thread() { @Override public void run() { System.out.println(getState()); } }; System.out.println(thread.getState()); thread.start(); try {
Tambahkan WAITING dan BLOCKED: public static void main(String[] strings) throws InterruptedException { Object lock = new Object(); Thread thread = new Thread() { @Override public void run() { try { synchronized (lock) { lock.notifyAll(); lock.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } }; synchronized (lock){ thread.start();
Untuk TIMED_WAITING, ubah sedikit kode yang sama: public static void main(String[] strings) throws InterruptedException { Object lock = new Object(); Thread thread = new Thread() { @Override public void run() { try { synchronized (lock) { lock.notifyAll(); lock.wait(3000); } } catch (InterruptedException e) { e.printStackTrace(); } } }; synchronized (lock) { thread.start();
8.1. Sinkronisasi utas
Tugas:Tulis program di mana dua utas dibuat yang menampilkan nama mereka pada konsol secara bergantian.Solusi: class StepThread extends Thread {
8.2. Pabrikan-konsumen
Salah satu tugas multithreading klasik. Diberi dua aliran - produsen dan konsumen. Pabrikan menghasilkan beberapa data (dalam contoh, angka). Pabrikan “mengkonsumsinya”.Dua aliran berbagi buffer data umum, yang ukurannya terbatas. Jika buffer kosong, konsumen harus menunggu data muncul di sana. Jika buffer penuh, pabrikan harus menunggu sampai konsumen mengambil data dan tempat itu menjadi gratis.Pabrikan:
Konsumen:
Buat dan jalankan: public static void main(String[] strings) { LinkedList<Double> sharedQueue = new LinkedList<>(); int size = 4; Thread prodThread = new Thread(new Producer(sharedQueue, size), "Producer"); Thread consThread = new Thread(new Consumer(sharedQueue), "Consumer"); prodThread.start(); consThread.start(); }
9.0. Anotasi sendiri - pembuatan dan penggunaan
Saya biasanya memberikan tugas ini ketika datang ke anotasi dan refleksi. Pada saat yang sama, Anda dapat berbicara tentang Pelaksana , ThreadPoolExecutor , dan lainnya.Tugas:Buat anotasi Ulangi dengan parameter integer.Memperpanjang kelas ThreadPoolExecutor dan mengganti metode yang mengeksekusi sebagai berikut: jika contoh dari Runnable dijelaskan dengan Ulangi , maka metode yang dijalankan dijalankan beberapa kali (jumlah yang ditentukan oleh parameter di Ulangi ).Yaitu, dengan menulis kelas ini: @Repeat(3) class MyRunnable implements Runnable{ @Override public void run() { System.out.println("Hello!"); } }
dan menggunakannya: public static void main(String[] strings) { CustomThreadPoolExecutor customThreadPoolExecutor = new CustomThreadPoolExecutor(10); customThreadPoolExecutor.execute(new MyRunnable()); }
Kita harus melihat: Hello! Hello! Hello!
Solusi: @Retention(RetentionPolicy.RUNTIME) @interface Repeat { int value(); } class CustomThreadPoolExecutor extends ThreadPoolExecutor { public CustomThreadPoolExecutor(int corePoolSize) {
Tugas akhir dan lainnya
Selama kursus, saya memberi siswa beberapa tugas sulit - untuk seluruh pelajaran. Diperlukan untuk menulis program kecil menggunakan yang dipelajari sebelumnya. Ngomong-ngomong, kompleksitas sering muncul di sini. Solusi untuk masalah menulis satu metode adalah satu hal, tetapi untuk menghasilkan sebuah algoritma, ingat semua yang Anda pelajari sebelumnya dan juga menulis 50 baris di Jawa segera sangat berbeda. Tetapi dalam pelajaran, saya dapat mendorong mereka ke arah yang benar, membantu menyelesaikan masalah, merendahkan, menemukan kelas dan metode yang tepat, dan sebagainya. Beberapa tugas ini dijelaskan di bawah ini. Dalam formulir ini, saya memberikannya kepada siswa saya.Selain itu, pada akhir kursus semua orang harus menyelesaikan tugas akhir. Yaitu, di rumah, sendiri, menulis sebuah program. Sedikit lebih rumit. Saya memberi Anda kesempatan untuk memilih satu dari beberapa opsi. Ngomong-ngomong, fakta yang menarik adalah bahwa Anda perlu menulis setidaknya satu program, atau Anda dapat menulis beberapa sekaligus. Tampaknya saya hanya ingat satu orang yang menulis lebih dari satu.10.0 Jumlah batasan jalan
Sebuah tugas kecil yang menunjukkan bagaimana Java dapat diterapkan untuk memecahkan masalah praktis.Persiapan data:Dari portal data terbuka St. Petersburg, kami memuat data tentang pembatasan lalu lintas untuk periode produksi dalam format csv .Tugas:Diperlukan untuk menentukan berapa banyak pembatasan jalan yang berlaku di kota pada tanggal tertentu.Program ini menggunakan dua parameter sebagai argumen:yaitu dimulai sebagai berikut: java TrafficBlocks "PATH_TO_CSV_FILE" dd.MM.yyyy
Diperlukan untuk menyimpulkan jumlah pembatasan lalu lintas yang berlaku pada tanggal ini.Algoritma teladanBy the way, untuk semua waktu hanya satu orang memperhatikan bahwa format tanggal dalam data (yyyyMMdd) adalah sedemikian rupa sehingga mereka tidak dapat diurai, tetapi dibandingkan sebagai string. Jadi solusinya bisa disederhanakan. Saya memberikan tugas ini setelah berbicara tentang Date, Calendar, DateFormat , jadi saya berbicara tentang penyederhanaan ini ketika mereka sudah menulis semuanya.Saya tidak membawa solusi di sini, mereka bisa sangat berbeda dan masing-masing harus dilihat secara individual.10.1.Pencarian Wikipedia. Dalam program konsol
Tugas:Tulis program yang membaca permintaan pencarian dari konsol dan menampilkan hasil pencarian di Wikipedia. Tugas ini dibagi menjadi 4 tahap:- Baca permintaan
- Buat permintaan ke server
- Uraikan jawabannya
- Hasil cetak
Poin pertama dan keempat tidak perlu banyak penjelasan, mari kita memikirkan permintaan ke server.Tugas ini juga dapat dibagi menjadi beberapa tahap:- Minta Pembuatan
- Permintaan server
- Mempersiapkan pemrosesan respons
- Pemrosesan tanggapan
Mari kita pertimbangkan ini secara lebih rinci: PembuatanpermintaanAPI menyediakan kemampuan untuk melakukan permintaan pencarian tanpa kunci. Dengan cara ini, kira-kira: https://ru.wikipedia.org/w/api.php?action=query&list=search&utf8=&format=json&srsearch="Java"
Anda dapat membuka tautan ini di peramban dan melihat hasil permintaan.Namun, agar permintaan berhasil, Anda harus menghapus karakter yang tidak valid dari tautan, yaitu, lakukan Persen-penyandian , yang juga Penyandian URL.Untuk melakukan ini, di Jawa, Anda bisa menggunakan metode penyandian statis di kelas URLEncoder , seperti ini: street = URLEncoder.encode(street, "UTF-8");
Itu saja, URL sudah siap! Sekarang tetap membuat permintaan ke server ...Permintaan ke serverUntuk permintaan GET dan POST, Anda dapat menggunakan kelas HttpURLConnection . Ini yang paling sederhana. Cukup buat, buka koneksi dan dapatkan InputStream . Kami bahkan tidak harus membacanya, Gson akan melakukannya untuk kami .Anda juga dapat menggunakan retrofit , atau yang serupa.Bersiap untuk memproses responsServer mengembalikan data dalam format JSON .Tetapi kita tidak perlu menguraikannya secara manual, untuk ini ada perpustakaan Gson dari Google.Contohnya ada di sini:https://github.com/google/gsonhttps://habrahabr.ru/company/naumen/blog/228279/Jika ada waktu tersisa, Anda dapat menulis tanda terima dari artikel yang dipilih selama pencarian dan seterusnya.10.2. Tugas akhir - utilitas konsol untuk mengunduh file melalui HTTP
Utilitas konsol untuk mengunduh file melalui HTTP ... apakah terdengar familiar? Ya, ini dia - Kisah satu tugas ujian . Semuanya logis - tugas terakhir dari kursus Java adalah pada tingkat yang sama dengan tugas tes untuk posisi pengembang Java Junior.Dan ini adalah tugas yang sangat bagus - tidak rumit, tetapi mencakup berbagai topik. Dan Anda dapat segera melihat bagaimana penulis menyusun kode, menggunakan berbagai pendekatan dan pola, menggunakan bahasa itu sendiri dan pustaka standar.10.3. Tugas akhir - cuaca Telegram-bot
Tugas:Tulis bot untuk Telegram, yang akan menjadi:- .
- , . /subscribe. (/unsubscribe).
Anda dapat menggunakan https://openweathermap.org/api untuk mendapatkan perkiraan .Tugas ini lebih pada kemampuan dan kemampuan untuk memahami teknologi baru (bot-api) dan perpustakaan yang berbeda. Dan Anda perlu mengatur VPN! Dan Anda harus menulis kodenya, tentu saja.Omong-omong, fakta yang menarik adalah bahwa sebagian besar siswa mengabaikan frasa “mengirim lokasi” dan kemungkinan mengirimkannya. Mereka menulis bot yang mengharapkan nama kota. Saya tidak tahu kenapa. Ini sering bekerja dengan buruk , kode menjadi sedikit lebih rumit, tetapi mereka terus melakukannya.10.4. Tugas akhir - pengenalan tulisan tangan
Tujuan:Menerapkan program untuk mengklasifikasikan angka tulisan tangan.Tugas ini sudah lebih fokus pada implementasi algoritma, kemampuan untuk memahami itu. Biasanya kode untuk siswa tidak terlalu terstruktur.Deskripsi tugasSebagai set data yang akan dipelajari, basis gambar digit tulisan tangan MNIST akan digunakan . Gambar dalam database ini memiliki resolusi 28x28 dan disimpan sebagai satu set nilai skala abu-abu. Seluruh basis data dibagi menjadi dua bagian: pelatihan, yang terdiri dari 50.000 gambar, dan uji - 10.000 gambar.Untuk mengatasi masalah ini, diusulkan untuk menerapkan metode k tetangga terdekat- Algoritma metrik untuk klasifikasi objek secara otomatis. Prinsip dasar dari metode tetangga terdekat adalah bahwa objek ditugaskan ke kelas yang paling umum di antara tetangga elemen ini.Tetangga diambil berdasarkan banyak objek yang kelasnya sudah diketahui, dan, berdasarkan nilai kunci k untuk metode ini, dihitung kelas mana yang paling banyak jumlahnya. Sebagai jarak antara objek, Anda dapat menggunakan metrik Euclidean, yaitu jarak yang biasa antara titik-titik di ruang angkasa.Persyaratan Andaharus menulis sebuah program yang akan mengenali nomor tulisan tangan. Seharusnya dimungkinkan untuk menginisialisasi kelas tertentu dengan data untuk pelatihan dan menyediakan metode untuk mengenali gambar tunggal.Selain implementasi algoritme itu sendiri, Anda harus menulis kode untuk memeriksa akurasinya (menghitung tingkat kesalahan). Untuk melakukan ini, gunakan 10.000 gambar uji.Selain menghitung akurasi, diusulkan untuk melakukan percobaan: alih-alih metrik Euclidean, gunakan jarak blok kota , sudut antara vektor atau sesuatu yang lain, dan periksa kualitas pengenalan.OpsionalJika semuanya bekerja dengan baik, maka Anda dapat sedikit memperumit tugas. Dengan menambahkan, misalnya, penghapusan kebisingan (emisi) atau penggunaan metode jendela Parzenovsky untuk meningkatkan akurasi.Beberapa kata lagi
Jika Anda memiliki tugas keren yang dapat Anda tawarkan kepada siswa (perkiraan waktu solusi adalah satu atau dua jam), kemudian bagikan dalam komentar.