JavaRush /Blog Java /Random-VI /Nghỉ giải lao #92. 20 câu hỏi phỏng vấn Java thường gặp

Nghỉ giải lao #92. 20 câu hỏi phỏng vấn Java thường gặp

Xuất bản trong nhóm
Nguồn: Dev.to Xin chào các bạn lập trình viên, tôi đã tổng hợp một danh sách các câu hỏi phỏng vấn Java cơ bản mà mọi lập trình viên nên biết.

1. Làm cách nào để đảo ngược một chuỗi trong Java mà không sử dụng phương thức Reverse()?

Trả lời: Không có phương thức Reverse() tiêu chuẩn trong Java , mặc dù phương thức Reverse() tồn tại trong một số thư viện như StringBuffer hoặc StringBuilder . Vì vậy, câu hỏi đảo mảng xuất hiện rất thường xuyên trong các cuộc phỏng vấn. Dưới đây là một thuật toán đơn giản có thể được sử dụng để đảo ngược một mảng.
public class StringReverse {

    public static void main(String[] args) {

        String str = "Flexiple";
        System.out.println(reverse(str));
    }

    public static String reverse(String in) {
        if (in == null)
            throw new IllegalArgumentException("Null is not valid");

        StringBuilder out = new StringBuilder();

        char[] chars = in.toCharArray();

        for (int i = chars.length - 1; i >= 0; i--)
            out.append(chars[i]);

        return out.toString();
    }
}

2. Viết đoạn mã thực hiện dãy Fibonacci bằng đệ quy

Trả lời: Đoạn mã bên dưới triển khai dãy Fibonacci bằng cách sử dụng đệ quy. Câu hỏi này cũng rất phổ biến trong các cuộc phỏng vấn Java.
public class FibonacciNumbers {
    public static int fibonacci(int n) {
        if (n <= 1)
            return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }


    public static void main(String args[]) {
        int n = 10;
        System.out.println(fibonacci(n));
    }
}

3. Làm cách nào để xóa khoảng trắng khỏi chuỗi trong Java?

Trả lời: Phương thức Strip() là một phương thức chuỗi loại bỏ tất cả các khoảng trắng ở đầu và cuối. Strip() sử dụng phương thức Character.isWhitespace() nội bộ để kiểm tra khoảng trắng. Nó phát hiện khoảng trắng bằng cách sử dụng các ký tự Unicode và là cách được khuyến nghị để xóa khoảng trắng. Các phương pháp thay thế StripLeading()StripTrailing() cũng có thể được sử dụng . Chúng sẽ giúp ích nếu bạn chỉ muốn loại bỏ các khoảng trắng ở đầu hoặc cuối tương ứng. Đoạn mã dưới đây là một ví dụ về việc sử dụng phương thức Strip() .
String s = "  flexiple ";

s = s.strip();

System.out.println(s);

4. Nguyên nhân gây ra tình huống bế tắc? Viết code tạo deadlock

Trả lời: Tình huống bế tắc xảy ra khi hai luồng yêu cầu cùng một khóa để thực thi. Những tình huống này xảy ra khi cả hai luồng đã có được một khóa và đang chờ lấy một khóa khác. Tuy nhiên, vì cả hai luồng đều đang chờ luồng kia thực thi nên chúng chặn lẫn nhau, gây ra bế tắc. Các chương trình đa luồng gặp phải tình trạng bế tắc vì từ khóa được đồng bộ hóa được sử dụng để làm cho các luồng phương thức trở nên an toàn. Điều này có nghĩa là chỉ một luồng có thể chặn và sử dụng phương thức được đồng bộ hóa. Các luồng khác phải đợi luồng hiện tại hoàn thành. Đoạn mã dưới đây tạo ra hai luồng bị bế tắc.
class Util
{
    static void sleep(long millis)
    {
        try
        {
            Thread.sleep(millis);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
class Shared
{
    synchronized void test1(Shared s2)
    {
        System.out.println("test1-begin");
        Util.sleep(1000);

        s2.test2();
        System.out.println("test1-end");
    }

    synchronized void test2()
    {
        System.out.println("test2-begin");
        Util.sleep(1000);

        System.out.println("test2-end");
    }
}

class Thread1 extends Thread
{
    private Shared s1;
    private Shared s2;

    public Thread1(Shared s1, Shared s2)
    {
        this.s1 = s1;
        this.s2 = s2;
    }

    @Override
    public void run()
    {
        s1.test1(s2);
    }
}

class Thread2 extends Thread
{
    private Shared s1;
    private Shared s2;

    public Thread2(Shared s1, Shared s2)
    {
        this.s1 = s1;
        this.s2 = s2;
    }

    @Override
    public void run()
    {
        s2.test2(s1);
    }
}

public class Deadlock
{
    public static void main(String[] args)
    {
        Shared s1 = new Shared();

        Shared s2 = new Shared();

        Thread1 t1 = new Thread1(s1, s2);
        t1.start();

        Thread2 t2 = new Thread2(s1, s2);
        t2.start();

        Util.sleep(2000);
    }
}

5. Viết mã Java để in ngày ở định dạng cụ thể

Trả lời: Lớp SimpleDateFormat giúp chuyển đổi ngày tháng từ định dạng này sang định dạng khác. Phương pháp này cũng cho phép người dùng sử dụng định dạng chuỗi ngày tháng và thay đổi nó sang định dạng mong muốn. Đoạn mã dưới đây chuyển đổi ngày sang định dạng chuẩn: DD/MM/YYYY
import java.text.SimpleDateFormat;
import java.util.Date;
public class CurrentDateTimeExample2 {
public static void main(String[] args) {
    SimpleDateFormat formatter = new SimpleDateFormat("DD/MM/YYYY HH:mm:ss");
    Date date = new Date();
    System.out.println(formatter.format(date));
}
}
Đoạn mã để chuyển đổi ngày thành MM/DD/YYYY:
import java.text.SimpleDateFormat;
import java.util.Date;
public class CurrentDateTimeExample2 {
public static void main(String[] args) {
    SimpleDateFormat formatter = new SimpleDateFormat("MM/DD/YYYY HH:mm:ss");
    Date date = new Date();
    System.out.println(formatter.format(date));
}
}

6. Làm cách nào để sắp xếp HashMap theo giá trị của nó?

Trả lời: HashMaps được sử dụng để triển khai giao diện bản đồ. Chúng cho phép người dùng lưu trữ các cặp khóa-giá trị, nhưng khóa phải là duy nhất. HashMap không phải là các bộ sưu tập được sắp xếp theo thứ tự và việc sắp xếp chúng không có ý nghĩa gì, nhưng vì việc sắp xếp các bản đồ băm có thể khá phức tạp nên chúng là một câu hỏi phổ biến trong các cuộc phỏng vấn Java. Mã bên dưới hiển thị cách triển khai HashMaps .
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class SortHashMap {

    public static void main(String[] args) {
        Map scores = new HashMap<>();

        scores.put("John", 6);
        scores.put("Carol", 8);
        scores.put("Martin", 9);
        scores.put("Mona", 7);
        scores.put("Eric", 5);

        System.out.println(scores);

        scores = sortByValue(scores);

        System.out.println(scores);

    }

    private static Map sortByValue(Map scores) {
        Map sorted = new LinkedHashMap<>();

        Set> entrySet = scores.entrySet();
        System.out.println(entrySet);

        List> entryList = new ArrayList<>(entrySet);
        System.out.println(entryList);

        entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));
        System.out.println(entryList);

        for (Entry e : entryList)
            sorted.put(e.getKey(), e.getValue());

        return sorted;
    }

}

7. Phương thức forEach() làm gì? Giải thích bằng một ví dụ

Trả lời: forEach() là một phương thức được sử dụng để lặp lại các đối tượng trong Java. Nhưng không giống như các vòng lặp khác, ở đây bộ đếm vòng lặp không được khai báo hoặc khởi tạo mà thay vào đó, biến được truyền dưới dạng một vòng lặp. Vì vậy, forEach() thường được sử dụng với mảng hoặc các lớp tập hợp. Cú pháp:
for (type var : array)
{
    statements using var;
}
Ví dụ về việc sử dụng forEach() :
class ExampleForEach
{
    public static void main(String[] arg)
    {
        {
            int[] scores = { 10, 13, 9, 11, 11};

            int highest_score = maximum(scores);
            System.out.println(highest_scores);
        }
    }
    public static int maximum(int[] numbers)
    {
        int max = numbers[0];

        // for each loop
        for (int n : numbers)
        {
            if (n > max)
            {
                max = n;
            }
        }
    return max;
    }
}

8. Giao diện chức năng là gì và chúng được tạo ra như thế nào?

Trả lời: Một giao diện chỉ chứa một phương thức trừu tượng được gọi là giao diện chức năng. Sau đó, các giao diện chức năng chỉ có thể có một chức năng, tuy nhiên chúng có thể chứa nhiều phương thức mặc định. Trong Java 8, biểu thức lambda có thể được sử dụng để khởi tạo các giao diện chức năng, giúp mọi việc trở nên dễ dàng hơn nhiều. Ví dụ về các giao diện chức năng: ActionListener , Comparable . Đây là mã được sử dụng để xác định giao diện chức năng.
@FunctionalInterface
interface Foo {
    void test();
}

9. Mô tả quá tải bằng ví dụ

Trả lời: Quá tải là quá trình giải quyết nhiều phương thức có cùng tên nhưng khác nhau tùy thuộc vào chữ ký, kiểu dữ liệu hoặc số lượng tham số của chúng. Quá tải cho phép người dùng sử dụng lại một phương thức duy nhất thay vì tạo và ghi nhớ nhiều phương thức. Nói tóm lại, quá tải có liên quan đến tính đa hình trong thời gian biên dịch. Mã quá tải phương thức ví dụ:
public class Sum {

    public int sum(int x, int y)
    {
        return (x + y);
    }

    public int sum(int x, int y, int z)
    {
        return (x + y + z);
    }

    public double sum(double x, double y)
    {
        return (x + y);
    }

    public static void main(String args[])
    {
        Sum s = new Sum();
        System.out.println(s.sum(10, 20));
        System.out.println(s.sum(10, 20, 30));
        System.out.println(s.sum(10.5, 20.5));
    }
}

10. Mô tả ghi đè bằng ví dụ

Trả lời: Ghi đè là một tính năng trong Java cho phép các lớp con hoặc lớp con cung cấp cách triển khai riêng cho một phương thức hiện có trong lớp cha. Khi một phương thức trong lớp con có cùng tên, tham số và kiểu trả về với lớp cha, thì phương thức đó sẽ ghi đè phương thức trong lớp cha. Và phiên bản của phương thức được gọi sẽ xác định phương thức nào sẽ được thực thi. Ghi đè là một cách để đạt được tính đa hình trong thời gian chạy. Ví dụ về mã ghi đè phương thức:
class Parent {
    void show()
    {
        System.out.println("Parent's show()");
    }
}

class Child extends Parent {
    @Override
    void show()
    {
        System.out.println("Child's show()");
    }
}

class Main {
    public static void main(String[] args)
    {
        Parent obj1 = new Parent();
        obj1.show();

        Parent obj2 = new Child();
        obj2.show();
    }
}

11. Tìm kiếm nhị phân là gì? Điều này được thực hiện như thế nào?

Trả lời: Thuật toán tìm kiếm nhị phân được sử dụng để tìm một giá trị trong một mảng hoặc loại bộ sưu tập đã được sắp xếp. Phương pháp tìm kiếm này nhanh hơn đáng kể so với phương pháp tìm kiếm tuyến tính. Tìm kiếm nhị phân chia mảng thành các tập hợp nhỏ hơn và sau đó áp dụng các quy tắc để kiểm tra khóa đầu vào. Các giai đoạn thực hiện tìm kiếm nhị phân (binary):
  • Sắp xếp mảng theo thứ tự tăng dần.
  • Tìm giá trị trung bình của mảng và so sánh nó với khóa.
  • Nếu khóa bằng giá trị trung bình, trả về true.
  • Nếu sai, hãy kiểm tra xem khóa có lớn hơn hay nhỏ hơn giá trị trung bình hay không.
  • Tiếp theo, dựa vào kết quả mà kiểm tra phím ở nửa trên hoặc nửa dưới tương ứng.
  • Lặp lại và so sánh từng giá trị với khóa.
Đoạn mã thực hiện tìm kiếm nhị phân:
import java.util.Scanner;

public class BinarySearch {

    public static void main(String[] args) {

        Scanner commandReader = new Scanner(System.in);
        System.out.println("Enter total number of elements : ");
        int length = commandReader.nextInt();
        int[] input = new int[length];

        System.out.printf("Enter %d integers %n", length);
        for (int i = 0; i < length; i++) {
            input[i] = commandReader.nextInt();
        }

        System.out.println("Please enter number to be searched in array
                                    (sorted order)");
        int key = commandReader.nextInt();

        int index = performBinarySearch(input, key);

        if (index == -1) {
            System.out.printf("Sorry, %d is not found in array %n", key);
        } else {
            System.out.printf("%d is found in array at index %d %n", key,
                                                         index);
        }

        commandReader.close();

    }


    public static int performBinarySearch(int[] input, int number) {
        int low = 0;
        int high = input.length - 1;

        while (high >= low) {
            int middle = (low + high) / 2;
            if (input[middle] == number) {
                return middle;
            } else if (input[middle] < number) {
                low = middle + 1;
            } else if (input[middle] > number) {
                high = middle - 1;
            }
        }
        return -1;
    }

}

12. Phương pháp tốt nhất để ngăn chặn bế tắc trong Java là gì?

Trả lời:
  • Khóa lồng nhau: Nguyên nhân chính gây ra bế tắc là khi các khóa được truyền cho nhiều luồng. Việc tránh chặn nhiều luồng trong trường hợp một luồng có khối đã tồn tại có thể giúp ngăn ngừa bế tắc.
  • Sử dụng Thread.join() : Bế tắc cũng có thể xảy ra khi một luồng đang chờ tài nguyên từ một luồng khác. Tuy nhiên, trong những trường hợp như vậy, Thread.join() có thể được sử dụng với thời gian thực hiện tối đa.
  • Chỉ sử dụng khóa khi cần thiết: ​​Thực hành chỉ sử dụng khóa trên các phần tử khi cần thiết. Những ổ khóa không cần thiết là nguyên nhân chính gây ra bế tắc.

13. Viết mã triển khai bộ nhớ đệm LRU trong Java

Trả lời: LRU là viết tắt của Cache ít được sử dụng nhất. Sơ đồ bộ đệm LRU được sử dụng để xóa bộ đệm được sử dụng lần cuối. Quá trình này xảy ra khi bộ đệm hiện có đầy và trang mới đang được tham chiếu không có trong bộ đệm hiện có. Mã dưới đây cho thấy việc thực hiện:
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Iterator;

public class LRUCache {

    private Deque doublyQueue;

    private HashSet hashSet;

    private final int CACHE_SIZE;

    LRUCache(int capacity) {
        doublyQueue = new LinkedList<>();
        hashSet = new HashSet<>();
        CACHE_SIZE = capacity;
    }

    public void refer(int page) {
        if (!hashSet.contains(page)) {
            if (doublyQueue.size() == CACHE_SIZE) {
                int last = doublyQueue.removeLast();
                hashSet.remove(last);
            }
        }
        else {/* The found page may not be always the last element, even if it's an
            intermediate element that needs to be removed and added to the start
            of the Queue */
            doublyQueue.remove(page);
        }
        doublyQueue.push(page);
        hashSet.add(page);
    }

    public void display() {
        Iterator itr = doublyQueue.iterator();
        while (itr.hasNext()) {
            System.out.print(itr.next() + " ");
        }
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache(4);
        cache.refer(1);
        cache.refer(2);
        cache.refer(3);
        cache.refer(1);
        cache.refer(4);
        cache.refer(5);
        cache.refer(2);
        cache.refer(2);
        cache.refer(1);
        cache.display();
    }
}

14. Mảng được quay như thế nào tùy thuộc vào vị trí của K, ví dụ k = 2?

Trả lời: Đoạn mã quay (trả về) mảng tùy theo vị trí đã chỉ định. Mặc dù có vẻ đơn giản nhưng nó kiểm tra sự hiểu biết của bạn về vòng lặp và mảng và do đó là một câu hỏi phổ biến trong các cuộc phỏng vấn Java.
public static int[] rotateBruteForce(int[] nums, int k) {
 for (int i = 0; i < k; i++) {
 for (int j = nums.length - 1; j > 0; j--) {
 // move each number by 1 place
 int temp = nums[j];
 nums[j] = nums[j - 1];
 nums[j - 1] = temp;
 }
 System.out.println("Array rotation after "+(i+1)+" step");
 printArray(nums);
 System.out.println();
 }
 return nums;
 }

15. Hàng đợi trong Java là gì? Thực hiện chúng bằng cách sử dụng mảng.

Trả lời: Hàng đợi là các cấu trúc tuyến tính thể hiện thứ tự thực hiện theo nguyên tắc ai đến trước được phục vụ trước. Java cung cấp cách triển khai đơn giản hơn cho các kiểu dữ liệu trừu tượng như hàng đợi, ngăn xếp, v.v. Tuy nhiên, việc triển khai chúng bằng cách sử dụng mảng là một câu hỏi kiểm tra sự hiểu biết của bạn về khái niệm này. Hãy nhớ rằng việc triển khai mảng của hàng đợi không linh hoạt.
package org.arpit.java2blog;

public class QueueUsingArrayMain {

    private int capacity;
    int queueArr[];
    int front;
    int rear;
    int currentSize = 0;

    public QueueUsingArrayMain(int sizeOfQueue) {
        this.capacity = sizeOfQueue;
        front = 0;
        rear = -1;
        queueArr = new int[this.capacity];
    }

16. HeapSort là gì? Viết mã để thực hiện nó

Trả lời: HeapSort là phương pháp sắp xếp dựa trên cấu trúc dữ liệu heap nhị phân. Đống nhị phân là một cây nhị phân trong đó các phần tử được lưu trữ theo cách sao cho các giá trị trong nút cha lớn hơn (heap tối đa) hoặc nhỏ hơn (heap tối thiểu) so với các giá trị trong nút con. Mã để triển khai HeapSort trông như thế này:
public class HeapSort {
    public void sort(int arr[])
    {
        int n = arr.length;

        // Build heap (rearrange array)
        for (int i = n / 2 - 1; i >= 0; i--)
            heapify(arr, n, i);

        // One by one extract an element from heap
        for (int i = n - 1; i > 0; i--) {
            // Move current root to end
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            // call max heapify on the reduced heap
            heapify(arr, i, 0);
        }
    }

    // To heapify a subtree rooted with node i which is
    // an index in arr[]. n is size of heap
    void heapify(int arr[], int n, int i)
    {
        int largest = i; // Initialize largest as root
        int l = 2 * i + 1; // left = 2*i + 1
        int r = 2 * i + 2; // right = 2*i + 2

        // If left child is larger than root
        if (l < n && arr[l] > arr[largest])
            largest = l;

        // If right child is larger than largest so far
        if (r < n && arr[r] > arr[largest])
            largest = r;

        // If largest is not root
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;

            // Recursively heapify the affected sub-tree
            heapify(arr, n, largest);
        }
    }

    /* A utility function to print array of size n */
    static void printArray(int arr[])
    {
        int n = arr.length;
        for (int i = 0; i < n; ++i)
            System.out.print(arr[i] + " ");
        System.out.println();
    }

    // Driver code
    public static void main(String args[])
    {
        int arr[] = { 12, 11, 13, 5, 6, 7 };
        int n = arr.length;

        HeapSort ob = new HeapSort();
        ob.sort(arr);

        System.out.println("Sorted array is");
        printArray(arr);
    }
}

17. Ghi nhớ là gì?

Trả lời: Ghi nhớ là một phương pháp giúp giải quyết các vấn đề do lập trình động gây ra. Quá trình này đảm bảo rằng một phương thức nhất định sẽ không được thực thi nhiều lần cho cùng một dữ liệu đầu vào. Các giá trị trả về được lưu trữ trong bảng băm hoặc bản đồ băm và được sử dụng lại khi cần thiết. Đoạn mã dưới đây là một ví dụ về ghi nhớ theo chuỗi Fibonacci.
import java.io.*;

class GFG
{

// Fibonacci Series
// using Recursion
static int fib(int n)
{

    // Base case
    if (n <= 1)
        return n;

    // recursive calls
    return fib(n - 1) +
        fib(n - 2);
}

// Driver Code
public static void main (String[] args)
{
    int n = 6;
    System.out.println(fib(n));
}
}

18. Viết đoạn code thực hiện sắp xếp bong bóng

Trả lời: Đoạn mã dưới đây là một giải pháp sắp xếp bong bóng, đây cũng là một câu hỏi phổ biến trong các cuộc phỏng vấn Java.
public class BubbleSortExample {
    static void bubbleSort(int[] arr) {
        int n = arr.length;
        int temp = 0;
         for(int i=0; i < n; i++){
                 for(int j=1; j < (n-i); j++){
                          if(arr[j-1] > arr[j]){
                                 //swap elements
                                 temp = arr[j-1];
                                 arr[j-1] = arr[j];
                                 arr[j] = temp;
                         }
                 }
         }
    }
    public static void main(String[] args) {
                int arr[] ={3,60,35,2,45,320,5};
                System.out.println("Array Before Bubble Sort");
                for(int i=0; i < arr.length; i++){
                        System.out.print(arr[i] + " ");
                }
                System.out.println();
                bubbleSort(arr);//sorting array elements using bubble sort
                System.out.println("Array After Bubble Sort");
                for(int i=0; i < arr.length; i++){
                        System.out.print(arr[i] + " ");
                }

        }
}

19. Cấu trúc dữ liệu trie trong Java là gì?

Trả lời: Trie là cấu trúc dữ liệu lưu trữ dữ liệu theo cấu trúc cây có thứ tự bằng cách sử dụng các khóa lưu trữ. Vị trí của một nút trong cây xác định khóa được liên kết với nút đó và các nút con của nút đó có chung một tiền tố. Nhờ cấu trúc này, các lần thử mang lại hiệu suất tốt hơn và cũng lấy dữ liệu nhanh hơn nhiều. Tuy nhiên, nhược điểm duy nhất của việc sử dụng gỗ là cần nhiều không gian lưu trữ hơn.

20. Viết đoạn mã chuyển đổi HashMap thành ArrayList

Trả lời: Đoạn mã dưới đây được sử dụng để chuyển đổi HashMap thành ArrayList .
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class Java8MapToListExamples
{
    public static void main(String[] args)
    {
        //Creating a HashMap object

        HashMap studentPerformanceMap = new HashMap();

        //Adding elements to HashMap

        studentPerformanceMap.put("John Kevin", "Average");

        studentPerformanceMap.put("Rakesh Sharma", "Good");

        studentPerformanceMap.put("Prachi D", "Very Good");

        studentPerformanceMap.put("Ivan Jose", "Very Bad");

        studentPerformanceMap.put("Smith Jacob", "Very Good");

        studentPerformanceMap.put("Anjali N", "Bad");

        //Getting Set of keys

        Set keySet = studentPerformanceMap.keySet();

        //Creating an ArrayList of keys

        ArrayList listOfKeys = new ArrayList(keySet);

        System.out.println("ArrayList Of Keys :");

        for (String key : listOfKeys)
        {
            System.out.println(key);
        }

        System.out.println("--------------------------");

        //Getting Collection of values

        Collection values = studentPerformanceMap.values();

        //Creating an ArrayList of values

        ArrayList listOfValues = new ArrayList(values);

        System.out.println("ArrayList Of Values :");

        for (String value : listOfValues)
        {
            System.out.println(value);
        }

        System.out.println("--------------------------");

        //Getting the Set of entries

        Set> entrySet = studentPerformanceMap.entrySet();

        //Creating an ArrayList Of Entry objects

        ArrayList> listOfEntry = new ArrayList>(entrySet);

        System.out.println("ArrayList of Key-Values :");

        for (Entry entry : listOfEntry)
        {
            System.out.println(entry.getKey()+" : "+entry.getValue());
        }
    }
}
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION