JavaRush /Java Blog /Random EN /Top 50 Java Core Interview Questions and Answers. Part 2

Top 50 Java Core Interview Questions and Answers. Part 2

Published in the Random EN group
Top 50 Java Core Interview Questions and Answers. Part 1 Top 50 Java Core Interview Questions and Answers.  Part 2 - 1

Collections

25. What is meant by Collections in Java?

Collection is a framework that is designed to store and manipulate objects. Used to perform the following operations:
  • search;
  • sorting;
  • manipulation;
  • addition;
  • deletion.
All classes and interfaces for the Collection framework are in java.utilthe package.

26. What classes and interfaces are available in the Collection framework?

Interfaces:
  • Collection;
  • List;
  • Set;
  • Map;
  • Sorted Set;
  • Sorted Map;
  • Queue.
Classes:
  • Lists:
    1. ArrayList;
    2. LinkedList;
    3. Vector(deprecated).
  • Sets:
    1. HashSet;
    2. LinkedHashSet;
    3. TreeSet.
  • Maps:
    1. HashMap
    2. TreeMap
    3. HashTable (deprecated)
    4. LinkedHashMap
  • Queue
    1. Priority Queue.

27. What is meant by sorted and ordered in collections?

Ordered:

This means that the items that are stored in the collection are based on the values ​​added to the collection. This way we can iterate through the values ​​from the collection in a specific order. In other words, this means that the elements of the collection have their own specific order according to which they are arranged. For better understanding, a collection that is not ordered stores its elements in a random order. For example, Set.

Sorted:

This means that a group of elements is sorted into a collection based on the collection element's data. That is, not only is the collection ordered, but also the order of the elements depends on their values. This order may change if you sort by a different element value.

28. What collections are there with a List interface? How do you work with List?

The values ​​of elements in a sheet are based on their index—they are ordered by index. Repetitions of elements are allowed (that is, you can add the same object to the collection several times and it will be fine).

ArrayList:

The most common collection. Essentially, it is an array with a dynamically expanding size. The job of managing the size of the array rests with the collection. It's important for us to understand that in most cases this is what we need to use. Peculiarities:
  • fast search and quick index search;
  • the collection is ordered by index, but not sorted;
  • implements the RandomAccess interface;
  • slowly adding to the middle of the list.
Example:

public class A {

   public static void main(String[] args) {
       ArrayList names = new ArrayList<>();
       names.add("John");
       names.add("John");
       names.add("Roman");
       names.add("Ivan");
   }

}
>> output

   [John, John, Roman, Ivan]
The output shows that these are repeatable elements. They are displayed in the order in which they were recorded. What else to read? Yes, there is a lot of information, you don’t even need to leave JavaRush:

Linked List:

This is a collection in which each element has a link to the previous and next elements. These links allow you to move from one element to another. When adding an element, the links to the previous and next elements simply change: Top 50 Java Core Interview Questions and Answers.  Part 2 - 2
  • elements are connected to each other, that is, a doubly linked list is implemented;
  • the overall speed of operation is noticeably lower than in ArrayList;
  • an excellent choice for a large number of inserts and deletions into the middle of an array;
  • implements the Queue and Deque list interfaces, and therefore has their methods for working.
Example:

LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");

29. Tell us about the Map collection and its implementations?

Map is a key-value collection. There is a unique key and a value that matches that value. equals()Methods are also used hashcode()to determine the uniqueness of a key.

HashMap:

  • not sorted or ordered;
  • used if order and sorting are not important;
  • supports null key.
Example:

public class CollectionExample {

   public static void main(String[] args) {
       HashMap positions = new HashMap<>();
       positions.put("junior", "Ivan");
       positions.put("middle", "Roman");
       positions.put("senior", "Vasily");
       positions.put("team lead", "Anton");
       positions.put("arthitect", "Andrew");
       positions.put("senior", "John");
       System.out.println(positions);
   }
}

// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
The keys are always unique, so only one senior is recorded.

LinkedHashMap:

  • maintains insertion order;
  • slower than HashMap;
  • iteration is expected to be faster than in HashMap.
Example:

public class CollectionExample {

   public static void main(String[] args) {
       LinkedHashMap<String, String> positions = new LinkedHashMap<>();
       positions.put("junior", "Ivan");
       positions.put("middle", "Roman");
       positions.put("senior", "Vasily");
       positions.put("team lead", "Anton");
       positions.put("arthitect", "Andrew");
       positions.put("senior", "John");
       System.out.println(positions);
   }
}

// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}

TreeMap:

A map implementation that keeps the entries sorted according to the natural order of their keys, or better yet, using a comparator if one is provided in the constructor when the map is created. Example:
  1. Without comparator

    
    public class CollectionExample {
    
       public static void main(String[] args) {
           TreeMap<Integer, String> positions = new TreeMap<>();
           positions.put(1, "Ivan");
           positions.put(3, "Roman");
           positions.put(2, "Vasily");
           positions.put(10, "Anton");
           positions.put(7, "Andrew");
           positions.put(1, "John");
           System.out.println(positions);
       }
    }
    
    // вывод в консоль
    // {1=John, 2=Vasily, 3=Roman, 7=Andrew, 10=Anton}
  2. With comparator

    
    public class CollectionExample {
    
       public static void main(String[] args) {
           //используем реализацию Strategy Pattern'a и добавим компаратор:
           TreeMap<Integer, String> positions = new TreeMap<>(Comparator.reverseOrder());
           positions.put(1, "Ivan");
           positions.put(3, "Roman");
           positions.put(2, "Vasily");
           positions.put(10, "Anton");
           positions.put(7, "Andrew");
           positions.put(1, "John");
           System.out.println(positions);
       }
    }
    
    // вывод в консоль
    // {10=Anton, 7=Andrew, 3=Roman, 2=Vasily, 1=John}
We see that sorting in ascending order is implemented as standard, but this can be changed by adding a comparator to the constructor. TreeMap is well described here .

30. Tell us about the Set collection and its implementations?

Set is a set of unique elements, and this is its main feature. That is, Set does not allow the same elements to be repeated. It is important here that the objects that are added have a method implemented equals .

HashSet:

  • not sorted or ordered. Under the hood there is a HashMap with a placeholder for the value. See for yourself ;)
  • uses hashCode to add objects;
  • It should be used when you need to have unique objects and their order is not important.
Example:

public class CollectionExample {

   public static void main(String[] args) {
       HashSet<String> positions = new HashSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [senior, middle, team lead, architect, junior]
Here you can see that the “junior” element, which was added twice, is present only in a single instance. And the order is not the same as when adding.

LinkedHashSet:

  • ordered version of HashSet;
  • supports doubly linked list for all elements;
  • Use it when you need order in your iteration.
Example:

public class CollectionExample {

   public static void main(String[] args) {
       LinkedHashSet<String> positions = new LinkedHashSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [senior, middle, team lead, architect, junior]

TreeSet:

  • one of two sorted collections;
  • uses a red-black tree structure and ensures that elements are in ascending order;
  • Under the hood it's a TreeMap with a stub on the values. And the elements of the TreeSet are the keys to the TreeMap (see also ;)).
Example:

public class CollectionExample {

   public static void main(String[] args) {
       TreeSet<String> positions = new TreeSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [architect, junior, middle, senior, team lead]

Exceptions

31. What is Exception?

Exception is a problem that can occur at runtime. This is an exceptional situation that arises due to some reason. The exception inheritance diagram looks like this (you need to know it by heart ;)): Top 50 Java Core Interview Questions and Answers.  Part 2 - 3The diagram shows that, in general, all exceptions are divided into two groups - exceptions and error. Error - JVMs are used to display errors after which the application no longer makes sense. For example, StackOverFlowError, which says that the stack is full and the program can no longer run. Exception - exceptions that are generated programmatically in code. There are various exceptions, checked and unchecked, but the main thing is that they exist, and they can be caught and the application can continue to function. Exceptions, in turn, are further divided into those that inherit from RuntimeException and other descendants of Exception. There is enough information on this issue. We'll talk about what checked/unchecked exceptions are below.

32. How does the JVM handle exceptions?

How it works? As soon as an exception is thrown somewhere, runtime creates an Exception Object (denoted as ExcObj). It stores all the information necessary for work - the exception itself that was thrown and the place where it happened. Creation ExcObjand transmission to runtime is nothing more than “throwing an exception.” ExcObjcontains methods that can be used to get to the place where the exception was thrown. This set of methods is called Call Stack. Next, the runtime system looks for a method in the Call Stack that can handle our exception. If it does find a corresponding handler, that is, the exception type matches the type in the handler, everything is fine. If it doesn’t find it, then runtime passes everything to the default exception handler, which prepares a response and exits. This is what it looks like:

/**
* Пример, в котором показываются две опции — когда находится обработчик для исключения и когда нет.
*/
class ThrowerExceptionExample {

   public static void main(String[] args) throws IllegalAccessException {

       ThrowerExceptionExample example = new ThrowerExceptionExample();

       System.out.println(example.populateString());
   }

   /**
    * Здесь происходит перехват одного из возможных исключений — {@link IOException}.
    * А вот второй будет пробрасываться дальше вверх по вызову.
    */
   private String populateString() throws IllegalAccessException {
       try {
           return randomThrower();
       } catch (IOException e) {
           return "Caught IOException";
       }
   }

   /**
    * Здесь две опции: or бросается {@link IOException} or {@link IllegalAccessException}.
    * Выбирается случайным образом.
    */
   private String randomThrower() throws IOException, IllegalAccessException {
       if (new Random().nextBoolean()) {
           throw new IOException();
       } else {
           throw new IllegalAccessException();
       }
   }
}
In our case, CallStack will schematically look like:

randomThrower() => populateString() => main(String[] args)
There are two options: one or the other exception will be thrown randomly. For IOException everything is ok, if it is generated, then the result of the work will be: "Caught IOException". But if there is a second exception for which there is no handler, the program will stop with the following output:

Exception in thread "main" java.lang.IllegalAccessException
  at ThrowerExceptionExample.randomThrower(CollectionExample.java:38)
  at ThrowerExceptionExample.populateString(CollectionExample.java:24)
  at ThrowerExceptionExample.main(CollectionExample.java:15)

33. How do programmers handle exceptions?

In the questions above we have already used certain keywords to work with exceptions, now we need to talk about them in more detail. What are the keywords?
  • try
  • catch
  • throw
  • throws
  • finally
It's important to note that catch, throw and throws can only be used with java.lang.Throwable. This will not work with other types. Now we will discuss try, catch and finally.
  • try-catch-finallyis a construct that allows you to correctly catch and handle an exception.
  • try- there can only be one time, that’s where the logic happens;
  • catch— a block that receives some type of exception; there can be many of them. For example, a try block will throw several exceptions that have nothing to do with each other;
  • finally- “finally” this block. This is a block that will be executed in any case, regardless of what is done in try, catch.
This is what it looks like:

try {
   // сюда передают тот code, который может вызвать исключение.
} catch (IOException e) {
   // первый catch блок, который принимает IOException и все его подтипы(потомки).
   // Например, нет file при чтении, выпадает FileNotFoundException, и мы уже соответствующе
   // обрабатываем это.
} catch (IllegalAccessException e) {
   // если нужно, можно добавить больше одного catch блока, в этом нет проблем.
} catch (OneException | TwoException e) {
   // можно даже объединять несколько в один блок
} catch (Throwable t) {
   // а можно сказать, что мы принимаем ВСЁ))))
} finally {
   // этот блок может быть, а может и не быть.
   // и он точно выполнится.
}
Carefully read the description of the example and everything will be clear)

34. throw and throws in Java

throw

throwused when you need to explicitly create a new exception. It is used to create and throw custom exceptions. For example, exceptions related to validation. Usually, for validation, they inherit from RuntimeException. Example:

// пример пробрасывания исключения
throw new RuntimeException("because I can :D");
It is important that this construction can only be used by something that inherits from Throwable. That is, you cannot say this:

throw new String("How тебе такое, Илон Маск?");
Next, the thread’s work is terminated and the search begins for a handler that could process it. When it doesn’t find it, it goes to the method that called it, and so the search will go up the line of calls until it either finds the corresponding handler or leaves the application running. Let's look:

// Пример, который демонстрирует работу throw
class ThrowExample {

   void willThrow() throws IOException {
       throw new IOException("Because I Can!");
   }

   void doSomething() {
       System.out.println("Doing something");
       try {
           willThrow();
       } catch (IOException e) {
           System.out.println("IOException was successfully handled.");
       }
   }

   public static void main(String args[]) {
       ThrowExample throwExample = new ThrowExample();
       throwExample.doSomething();
   }
}
If we run the program, we get the following result:

Doing something
IOException was successfully handled.

throws

throws— a mechanism by which a method can throw one or more exceptions. They are added separated by commas. Let's see how easy and simple it is:

private Object willThrow() throws RuntimeException, IOException, FileNotFoundException
Moreover, it is important to note that there can be both checked and unchecked exceptions. Of course, unchecked exceptions may not be added to throws, but good manners say otherwise. If these are checkables, then using the method that generates them, you need to somehow process it. There are two options:
  1. Write try-catchwith the appropriate and above inheritance exception.
  2. Use it throwsin exactly the same way so that someone else already has this problem :D

35. Checked and Unchecked exceptions in Java

There are two types of exceptions in Java - checked and unchecked.

Checked exceptions:

These are exceptions that are checked at compile time. If some code in a method throws a checked exception during an exception, the method must either process it using try-catch, or forward it further. For example, which reads an image from the path "/users/romankh3/image.png", updates it in some way way (for us this is not important) and saves it back.

class CheckedImageExample {
   public static void main(String[] args) {
       File imageFile = new File("/users/romankh3/image.png");
       BufferedImage image = ImageIO.read(imageFile);
       updateAndSaveImage(image, imageFile);
   }

   private static void updateAndSaveImage(BufferedImage image, File imageFile) {
       ImageIO.write(image, "png", imageFile);
   }
}
Such code will not compile, since static methods ImageIO.read()throw ImageIO.write()an IOException, which is checked and must be handled accordingly. There are two options here that we have already discussed above: either use try-catch, or forward further. For better assimilation, we will do this and that. That is, updateAndSavewe’ll just forward it in the method, and then use it in the main method try-catch:

class CheckedImageExample {
   public static void main(String[] args) {
       File imageFile = new File("/users/romankh3/image.png");
       try {
           BufferedImage image = ImageIO.read(imageFile);
           updateAndSaveImage(image, imageFile);
       } catch (IOException e) {
           e.printStackTrace();
       }
   }

   private static void updateAndSaveImage(BufferedImage image, File imageFile) throws IOException {
       ImageIO.write(image, "png", imageFile);
   }
}

Unchecked exceptions:

These are the exceptions that are not checked at the compilation stage. That is, a method can generate a RuntimeException, but the compiler will not remind you to somehow handle it. As shown below, we have everything that inherits from RuntimeException and Error are unchecked. Top 50 Java Core Interview Questions and Answers.  Part 2 - 4Consider the following Java program. The code compiles fine, but throws an exception when run ArrayIndexOutOfBoundsException. The compiler allows it to compile because ArrayIndexOutOfBoundsExceptionit is an unchecked exception. A common situation with an array, which could be:

class CheckedImageExample {
   public static void main(String[] args) {
       int[] array = new int[3];
       array[5] = 12;
   }
}
The result will be:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
  at main(CheckedImageExample.java:12)
By the way, have you already noticed that in Java no one gives short names? The bigger, the better. He, Spring Framework, was very successful in this: just take some BeanFactoryPostProcessor class)))

36. What are try-with-resources?

This is a mechanism by which all resources must be closed correctly. It’s somehow not clear, right?) First of all, what is a resource... A resource is an object, after working with which you need to close it, that is, call the close(). A resource is all objects that implement an interface AutoClosable, which in turn implements an interface Closeable. It is important for us to understand that everything InputStreamis OutpuStreama resource and needs to be released correctly and successfully. This is exactly why we need to use try-with-resourcethe structure. Here's what it looks like:

private void unzipFile(File zipFile) throws IOException {
   try(ZipInputStream zipOutputStream = new ZipInputStream(new FileInputStream(zipFile))) {
       ZipEntry zipEntry = zipOutputStream.getNextEntry();
       while (zipEntry != null) {
          
       }
   }
}

private void saveZipEntry(ZipEntry zipEntry) {
   // логика сохранения
}
In this example, the resource is ZipInputStream, after working with which you will need to close it. And in order not to think about calling the method close(), we simply define this variable in a try block, as shown in the example, and within this block we do everything necessary. What does the example do? It will unzip the zip archive. To do this you need to use InputStream'om. You can define more than one variable; they are separated by a semicolon. What's the problem? But you can use finallya block, you might say. Here's an article that details the problems with this approach. It also describes the entire list of failures that can befall someone who neglects to use this design. I recommend reading it ;) In the final part there are questions/answers on the topic of Multithreading. My GitHub profile
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION