Java Practical Tasks - untuk kursus dan kegiatan lainnya

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-Rata
1.1 Sortir Array
1.2 Menemukan bilangan prima
1.3 Menghapus dari suatu array

Dasar-Dasar OOP


2.0 Merancang dan membuat kelas yang menggambarkan vektor
2.1 Menghasilkan elemen acak dengan bobot
2.2 Daftar Tertaut

Rekursi


3.0 Pencarian Biner
3.1 Temukan akar persamaan
3.2 Pohon Pencarian Biner

Warisan


4.0 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi
4.1 Menerapkan hierarki kelas yang menggambarkan angka tiga dimensi - 2
4.2 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 3
4.3 Menerapkan hierarki kelas yang menggambarkan bentuk tiga dimensi - 4

Garis


5.0 Kamus Frekuensi Surat

Kelas dan antarmuka abstrak


6.0 Konverter suhu
6.1. Stringbuilder dengan dukungan undo
6.2. Statebuilding Stringbuilder (pola pengamat)
6.4. Mengisi array dengan Function

Koleksi


7.0 Kamus Frekuensi Kata
7.1. Koleksi tanpa duplikat
7.2. ArrayList dan LinkedList
7.3. Tulis iterator di atas sebuah array
7.4. Tulis iterator pada array dua dimensi
7.5. Iterator yang bahkan lebih kompleks
7.6. Iterator melalui dua iterator
7.7. Menghitung Elemen
7.8. Ubah kunci dan nilai dalam Peta

Multithreading


8.0 Serikat
8.1. Sinkronisasi utas
8.2. Pabrikan Konsumen

Anotasi


9.0. Anotasi khusus - pembuatan dan penggunaan dengan refleksi

Tugas akhir dan lainnya


10.0 Jumlah batasan jalan
10.1. Pencarian Wikipedia. Dalam program konsol
10.2. Tugas akhir - utilitas konsol untuk mengunduh file melalui HTTP
10.3. Tugas akhir - cuaca Telegram-bot
10.4. Tugas akhir - pengenalan tulisan tangan

Dasar-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]; //      double min = array[0]; double avg = 0; for (int i = 0; i < array.length; i++) { if(max < array[i]) max = array[i]; if(min > array[i]) min = array[i]; avg += array[i]/array.length; } System.out.println("max = " + max); System.out.println("min = " + min); System.out.println("avg = " + avg); } 

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}; /* Arrays.toString: . https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html */ 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]; } } // Arrays.copyOf     nums    //   nums.length - offset return Arrays.copyOf(nums, nums.length - offset); } 

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; //      for (int i = 0; i < nums.length; i++) { if (nums[i] != val) { count++; } } int[] newArray = new int[count]; int offset = 0; //      , //       for(int i = 0; i< nums.length; i++){ if(nums[i] == val){ offset++; } else{ newArray[i - offset] = nums[i]; } } return newArray; } 


2.0. Merancang dan membuat kelas vektor


Tantangan:

Buat kelas yang menggambarkan vektor (dalam ruang tiga dimensi).

Ia harus memiliki:

  • konstruktor dengan parameter dalam bentuk daftar koordinat x, y, z
  • metode yang menghitung panjang vektor. Root dapat dihitung menggunakan Math.sqrt ():

     sqrtx2+y2+z2

  • metode perhitungan produk skalar:

    x1x2+y1y2+z1z2

  • metode menghitung produk vektor dengan vektor lain:

    (y1z2z1y2,z1x2x1z2,x1y2y1x2)

  • metode yang menghitung sudut antara vektor (atau cosinus sudut): cosinus sudut antara vektor sama dengan produk skalar vektor dibagi dengan produk modul (panjang) vektor:

     frac(a,b)|a| cdot|b|

  • metode penjumlahan dan perbedaan:

    (x1+x2,y1+y2,z1+z2)

    (x1x2,y1y2,z1z2)


  • metode statis yang mengambil bilangan bulat N dan mengembalikan array vektor acak berukuran N.

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 { //    private double x; private double y; private double z; //    public Vector(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } //  .     public double length() { return Math.sqrt(x * x + y * y + z * z); } // ,    public double scalarProduct(Vector vector) { return x * vector.x + y * vector.y + z * vector.z; } // ,    public Vector crossProduct(Vector vector) { return new Vector( y * vector.z - z * vector.y, z * vector.x - x * vector.z, x * vector.y - y * vector.x); } //     public double cos(Vector vector) { //       // multiply  length return scalarProduct(vector) / (length() * vector.length()); } public Vector add(Vector vector) { return new Vector( x + vector.x, y + vector.y, z + vector.z ); } public Vector subtract(Vector vector) { return new Vector( x - vector.x, y - vector.y, z - vector.z ); } public static Vector[] generate(int n){ Vector[] vectors = new Vector[n]; for(int i =0; i < n; i++){ vectors[i] = new Vector(Math.random(), Math.random(), Math.random()); } return vectors; } @Override public String toString() { return "Vector{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; } } 

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 { //    ,    private double values[]; public Vector(double[] values) { this.values = values; } //  .     public double length() { double sum = 0; for (int i = 0; i < values.length; i++) { sum += values[i] * values[i]; } return Math.sqrt(sum); } // ,    public double scalarProduct(Vector vector) { double res = 0; for (int i = 0; i < values.length; i++) { res += values[i] * vector.values[i]; } return res; } //     // public double crossProduct(Vector vector) { // // } //     public double cos(Vector vector) { return scalarProduct(vector) / (length() * vector.length()); } public Vector add(Vector vector) { double[] another = new double[values.length]; for (int i = 0; i < values.length; i++) { another[i] = values[i] + vector.values[i]; } return new Vector(another); } public Vector subtract(Vector vector) { double[] another = new double[values.length]; for (int i = 0; i < values.length; i++) { another[i] = values[i] - vector.values[i]; } return new Vector(another); } //   private static double[] generateRandomArray(int length) { double[] array = new double[length]; for (int i = 0; i < array.length; i++) { array[i] = Math.random(); } return array; } public static Vector[] generate(int n, int dimension) { Vector[] vectors = new Vector[n]; for (int i = 0; i < n; i++) { vectors[i] = new Vector(generateRandomArray(dimension)); } return vectors; } } 


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:

 /*     :  ,   —    .   ""     ,       ,        : |-|--|----------| 0-1--3----------13 ^ */ class RandomFromArray { private int[] values; //  private int[] weights; //  private int[] ranges; //    private int sum; //     public RandomFromArray(int[] values, int[] weights) { this.values = values; this.weights = weights; ranges = new int[values.length]; //     sum = 0; for (int weight : weights) { sum += weight; } //  ranges,   int lastSum = 0; for (int i = 0; i < ranges.length; i++) { ranges[i] = lastSum; lastSum += weights[i]; } } /*  ranges  ,        [0;sum],   ,   : */ public int getRandom() { int random = (int) (Math.random() * (sum - 1)); int ourRangeIndex = 0; for (int i = 0; i < ranges.length; i++) { if (ranges[i] > random) { break; } ourRangeIndex = i; } return values[ourRangeIndex]; } } 

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; //  public RandomFromArray(int[] values, int[] weights) { //     int sum = 0; for (int weight : weights) { sum += weight; } extended_values = new int[sum]; int cursor = 0; for(int i = 0; i < weights.length; i++){ for(int j = 0; j < weights[i]; j++){ extended_values[cursor++] = values[i]; } } } /*  extended_values  ,        [0; extended_values.length) */ public int getRandom() { int random = (int) (Math.random() * ( extended_values.length - 1)); return extended_values[random]; } } 

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. LinkedList

3.0 Pencarian biner


Tantangan:

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:

  /*  ,   .    ,  -1 */ 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); } /** *    {@link #binarySearchRecursively(double[], double)} * *    ,   ,   " ", *      .    low  high * * @param sortedArray   * @param key   * @param low     * @param high     * @return   */ private static int binarySearchRecursively (double[] sortedArray, double key, int low, int high) { int middle = (low + high) / 2; //  if (high < low) { //    return -1; } if (key == sortedArray[middle]) { //   return middle; } else if (key < sortedArray[middle]) { //     return binarySearchRecursively( sortedArray, key, low, middle - 1); } else { return binarySearchRecursively( //     sortedArray, key, middle + 1, high); } } //     private static double[] generateRandomArray(int length) { double[] array = new double[length]; for (int i = 0; i < array.length; i++) { array[i] = Math.random(); } return array; } public static void main(String[] args) { double[] array = generateRandomArray(100000000); Arrays.sort(array); //    /*  ,       ,   benchmarks . https://habr.com/ru/post/349914/     */ long time = System.currentTimeMillis(); //  , unix-time bruteForce(array, 0.5); System.out.println(System.currentTimeMillis() - time); time = System.currentTimeMillis(); binarySearchRecursively(array, 0.5); System.out.println(System.currentTimeMillis() - time); } 

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:

  //   public static double func(double x){ return Math.cos(Math.pow(x, 5)) + Math.pow(x, 4) - 345.3 * x - 23; } //   public static double solve(double start, double end){ if(end - start <= 0.001){ return start; } double x = start + (end - start) / 2; if(func(start) * func(x) > 0){ return solve(x, end); } else { return solve(start, x); } } public static void main(String[] args) { System.out.println(solve(0, 10)); } 

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 cepat
Implementasi Java dari pohon biner hash

Warisan


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 { //   public Ball(double radius) { super(Math.PI * Math.pow(radius, 3) * 4 / 3, radius); } } class Cylinder extends SolidOfRevolution { //   private double height; public Cylinder(double radius, double height) { super(Math.PI * radius * radius * height, radius); this.height = height; } } class Pyramid extends Shape{ private double height; private double s; //   public Pyramid(double height, double s) { super(height * s * 4 / 3); this.height = height; this.s = s; } } class Box extends Shape { private ArrayList<Shape> shapes = new ArrayList<>(); private double available; public Box(double available) { super(available); this.available = available; } public boolean add(Shape shape) { if (available >= shape.getVolume()) { shapes.add(shape); available -= shape.getVolume(); return true; } else { return false; } } } public class Main { public static void main(String[] args) { Ball ball = new Ball(4.5); Cylinder cylyinder = new Cylinder(2, 2); Pyramid pyramid = new Pyramid(100, 100); Box box = new Box(1000); System.out.println(box.add(ball)); // ok System.out.println(box.add(cylyinder)); // ok System.out.println(box.add(pyramid)); // failed } } 

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 { //   @Override public double getVolume() { return Math.PI * Math.pow(radius, 3) * 4 / 3; } public Ball(double radius) { super(radius); } } class Cylinder extends SolidOfRevolution { //   private double height; public Cylinder(double radius, double height) { super(radius); this.height = height; } @Override public double getVolume() { return Math.PI * radius * radius * height; } } class Pyramid extends Shape { private double height; private double s; //   public Pyramid(double height, double s) { this.height = height; this.s = s; } @Override public double getVolume() { return height * s * 4 / 3; } } class Box extends Shape { private ArrayList<Shape> shapes = new ArrayList<>(); private double available; private double volume; public Box(double available) { this.available = available; this.volume = available; } public boolean add(Shape shape) { if (available >= shape.getVolume()) { shapes.add(shape); available -= shape.getVolume(); return true; } else { return false; } } @Override public double getVolume() { return volume; } } public class Main { public static void main(String[] args) { Ball ball = new Ball(4.5); Cylinder cylyinder = new Cylinder(2, 2); Pyramid pyramid = new Pyramid(100, 100); Box box = new Box(1000); System.out.println(box.add(ball)); // ok System.out.println(box.add(cylyinder)); // ok System.out.println(box.add(pyramid)); // failed } } 

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 { //   @Override public double getVolume() { return Math.PI * Math.pow(radius, 3) * 4 / 3; } public Ball(double radius) { super(radius); } } class Cylinder extends SolidOfRevolution { //   private double height; public Cylinder(double radius, double height) { super(radius); this.height = height; } @Override public double getVolume() { return Math.PI * radius * radius * height; } } class Pyramid implements Shape { private double height; private double s; //   public Pyramid(double height, double s) { this.height = height; this.s = s; } @Override public double getVolume() { return height * s * 4 / 3; } } class Box implements Shape { private ArrayList<Shape> shapes = new ArrayList<>(); private double available; private double volume; public Box(double available) { this.available = available; this.volume = available; } public boolean add(Shape shape) { if (available >= shape.getVolume()) { shapes.add(shape); available -= shape.getVolume(); return true; } else { return false; } } @Override public double getVolume() { return volume; } public ArrayList<Shape> getShapes() { return shapes; } } public class Main { public static void main(String[] args) { Ball ball = new Ball(4.5); Cylinder cylyinder = new Cylinder(2, 2); Pyramid pyramid = new Pyramid(100, 100); Box box = new Box(1000); System.out.println(box.add(ball)); // ok System.out.println(box.add(cylyinder)); // ok System.out.println(box.add(pyramid)); // failed // Sorting: ArrayList<Shape> shapes = box.getShapes(); Collections.sort(shapes); // sorted by Volume! } } 

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
gambar


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:

  /** *      ,  *      , *    Map. * *    Map.Entry<Character, Integer>, *     (Character) * * @param text -  */ 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); //     - if((ch >= '' && ch <= '') || ch == ''){ map.compute(ch, (character, integer) -> integer == null ? 1 : integer + 1); } } ArrayList<Map.Entry<Character, Integer>> entries = new ArrayList<>(map.entrySet()); entries.sort((o1, o2) -> Character.compare(o1.getKey(), o2.getKey())); for(Map.Entry<Character, Integer> entry : entries){ System.out.println(entry.getKey() + " " + entry.getValue()); } } 

Atau lebih:

  /** *   Map. *    ,    *      *  * @param text */ 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:

 /** * StringBuilder    undo * java.lang.StringBuilder —    <b>final</b>, *   ,  . */ 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; //  /** * ,   . *     append,    *  "delete".   undo()  *  . */ private Stack<Action> actions = new Stack<>(); //  public UndoableStringBuilder() { stringBuilder = new StringBuilder(); } /** see {@link java.lang.AbstractStringBuilder#reverse()}  ,   reverse(),      —  reverse().    . */ public UndoableStringBuilder reverse() { stringBuilder.reverse(); Action action = new Action(){ public void undo() { stringBuilder.reverse(); } }; actions.add(action); return this; } public UndoableStringBuilder append(String str) { stringBuilder.append(str); Action action = new Action(){ public void undo() { stringBuilder.delete( stringBuilder.length() - str.length() -1, stringBuilder.length()); } }; actions.add(action); return this; } // .....    append   (. )...... public UndoableStringBuilder appendCodePoint(int codePoint) { int lenghtBefore = stringBuilder.length(); stringBuilder.appendCodePoint(codePoint); actions.add(new DeleteAction(stringBuilder.length() - lenghtBefore)); return this; } public UndoableStringBuilder delete(int start, int end) { String deleted = stringBuilder.substring(start, end); stringBuilder.delete(start, end); actions.add(() -> stringBuilder.insert(start, deleted)); return this; } public UndoableStringBuilder deleteCharAt(int index) { char deleted = stringBuilder.charAt(index); stringBuilder.deleteCharAt(index); actions.add(() -> stringBuilder.insert(index, deleted)); return this; } public UndoableStringBuilder replace(int start, int end, String str) { String deleted = stringBuilder.substring(start, end); stringBuilder.replace(start, end, str); actions.add(() -> stringBuilder.replace(start, end, deleted)); return this; } public UndoableStringBuilder insert(int index, char[] str, int offset, int len) { stringBuilder.insert(index, str, offset, len); actions.add(() -> stringBuilder.delete(index, len)); return this; } public UndoableStringBuilder insert(int offset, String str) { stringBuilder.insert(offset, str); actions.add(() -> stringBuilder.delete(offset, str.length())); return this; } // .....    insert   (. )...... public void undo(){ if(!actions.isEmpty()){ actions.pop().undo(); } } public String toString() { return stringBuilder.toString(); } } 

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:

 /** .  ,      UndoableStringBuilder,   onChange(). */ interface OnStringBuilderChangeListener { void onChange(OvservableStringBuilder stringBuilder); } class OvservableStringBuilder { // ,     private OnStringBuilderChangeListener onChangeListener; //  private StringBuilder stringBuilder; //   onChangeListener public void setOnChangeListener(OnStringBuilderChangeListener onChangeListener) { this.onChangeListener = onChangeListener; } public OvservableStringBuilder() { stringBuilder = new StringBuilder(); } private void notifyOnStringBuilderChangeListener(){ if(onChangeListener != null){ onChangeListener.onChange(this); } } public OvservableStringBuilder append(Object obj) { stringBuilder.append(obj); notifyOnStringBuilderChangeListener(); return this; } public OvservableStringBuilder replace(int start, int end, String str) { stringBuilder.replace(start, end, str); notifyOnStringBuilderChangeListener(); return this; } public OvservableStringBuilder insert(int index, char[] str, int offset, int len) { stringBuilder.insert(index, str, offset, len); notifyOnStringBuilderChangeListener(); return this; } // .......    .......... public String toString() { return stringBuilder.toString(); } } /**   OnStringBuilderChangeListener */ class MyListener implements OnStringBuilderChangeListener { /*   onChange    stringBuilder,  "" */ public void onChange(OvservableStringBuilder stringBuilder) { System.out.println("CHANGED: " + stringBuilder.toString()); } } public class Main { public static void main(String[] strings) { OvservableStringBuilder UndoableStringBuilder = new OvservableStringBuilder(); UndoableStringBuilder.setOnChangeListener(new MyListener()); UndoableStringBuilder.append("Hello"); UndoableStringBuilder.append(", "); UndoableStringBuilder.append("World!"); } } 

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 berlebihan
Periksa 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]; } } // Arrays.copyOf     array    //   array.length - offset return Arrays.copyOf(array, array.length - offset); } public static void main(String[] args) { String array[] = new String[]{"1rewf ", "feefewf", "a", null, "1"}; String[] newArray = (String[]) filter(array, new Filter() { @Override public boolean apply(Object o) { return o != null; } }); } } 

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]; } } // Arrays.copyOf     array    //   array.length - offset return Arrays.copyOf(array, array.length - offset); } public static void main(String[] args) { String array[] = new String[]{"1rewf ", "feefewf", "a", null, "1"}; String[] newArray = filter(array, s -> s != null); } } 

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); // 0, 1, 4, 9, 16 ..... } 

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 alfabet

7.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:

 /** * @author Irina Poroshina */ 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:

 /** * @author Irina Poroshina */ 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 { //         TERMINATED: thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(thread.getState()); 

Tambahkan WAITING dan BLOCKED:

  /** *   WAITING * * @param strings * @throws InterruptedException */ 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(); //   lock.wait(); //  ,     System.out.println(thread.getState()); // WAITING lock.notifyAll(); System.out.println(thread.getState()); // BLOCKED } } 

Untuk TIMED_WAITING, ubah sedikit kode yang sama:

  /** *   WAITING * * @param strings * @throws InterruptedException */ 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(); //   lock.wait(); //  ,     System.out.println(thread.getState()); // WAITING } } 

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 { //     lock private Object lock; public StepThread(Object object) { this.lock = object; } /** *  :   ,   , *     ,  ,    . * *     lock.notify()   *   ,  , *  lock   .    ,   *  lock.wait(),      .    . */ @Override public void run() { while (true) { synchronized (lock) { try { System.out.println(getName()); lock.notify(); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public class Main { public static void main(String[] strings) { Object lock = new Object(); new StepThread(lock).start(); new StepThread(lock).start(); } } 

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:

 // implements Runnable      class Producer implements Runnable { //   private final Queue<Double> sharedQueue; //   private final int SIZE; //  public Producer(Queue<Double> sharedQueue, int size) { this.sharedQueue = sharedQueue; this.SIZE = size; } @Override public void run() { //   while (true) { try { //     produce System.out.println("Produced: " + produce()); } catch (InterruptedException e) { e.printStackTrace(); } } } private double produce() throws InterruptedException { synchronized (sharedQueue) { //  synchronized if (sharedQueue.size() == SIZE) { //   ,   sharedQueue.wait(); } //    . double newValue = Math.random(); sharedQueue.add(newValue); //     ,    sharedQueue.notifyAll(); return newValue; } } } 

Konsumen:

 // implements Runnable      class Consumer implements Runnable { //   private final Queue<Double> sharedQueue; public Consumer(Queue<Double> sharedQueue) { this.sharedQueue = sharedQueue; } @Override public void run() { while (true) { try { System.out.println("Consumed: " + consume()); } catch (InterruptedException ex) { ex.printStackTrace(); } } } // ,      private Double consume() throws InterruptedException { synchronized (sharedQueue) { if (sharedQueue.isEmpty()) { //  ,   sharedQueue.wait(); } sharedQueue.notifyAll(); return sharedQueue.poll(); } } } 

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) { // why Integer.MAX_VALUE, 0m and TimeUnit.MILLISECONDS? // see Executors.newFixedThreadPool(int nThreads) super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); } @Override public void execute(Runnable command) { if (command != null) { Class<? extends Runnable> runnableClass = command.getClass(); Repeat repeat = runnableClass.getAnnotation(Repeat.class); for (int i = 0; i < (repeat != null ? repeat.value() : 1); i++) { super.execute(command); } } } } 

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:

  • Path ke file data
  • Tanggal

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 teladan


By 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:
  1. Baca permintaan
  2. Buat permintaan ke server
  3. Uraikan jawabannya
  4. Hasil cetak

Poin pertama dan keempat tidak perlu banyak penjelasan, mari kita memikirkan permintaan ke server.

Tugas ini juga dapat dibagi menjadi beberapa tahap:

  1. Minta Pembuatan
  2. Permintaan server
  3. Mempersiapkan pemrosesan respons
  4. Pemrosesan tanggapan

Mari kita pertimbangkan ini secara lebih rinci: Pembuatan

permintaan
API 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 server
Untuk 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 respons
Server 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/gson
https://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 tugas
Sebagai 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 Anda

harus 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.

Opsional

Jika 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.

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


All Articles