JavaRush /Blog Java /Random-ES /Las 50 preguntas y respuestas principales de las entrevis...

Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core. Parte 2

Publicado en el grupo Random-ES
Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core. Parte 1 Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core.  Parte 2 - 1

Colecciones

25. ¿Qué se entiende por colecciones en Java?

La colección es un marco diseñado para almacenar y manipular objetos. Se utiliza para realizar las siguientes operaciones:
  • buscar;
  • clasificación;
  • manipulación;
  • suma;
  • supresión.
Todas las clases e interfaces para el marco de la Colección están en java.utilel paquete.

26. ¿Qué clases e interfaces están disponibles en el marco de la Colección?

Interfaces:
  • Recopilación;
  • Lista;
  • Colocar;
  • Mapa;
  • Conjunto ordenado;
  • Mapa ordenado;
  • Cola.
Clases:
  • Liza:
    1. Lista de arreglo;
    2. Lista enlazada;
    3. Vector (en desuso).
  • Conjuntos:
    1. conjunto de hash;
    2. LinkedHashSet;
    3. Conjunto de árboles.
  • Mapas:
    1. HashMap
    2. ÁrbolMapa
    3. HashTable (en desuso)
    4. LinkedHashMap
  • Cola
    1. Cola de prioridad.

27. ¿Qué se entiende por ordenado y ordenado en colecciones?

Ordenado:

Esto significa que los elementos que se almacenan en la colección se basan en los valores agregados a la colección. De esta manera podemos recorrer los valores de la colección en un orden específico. En otras palabras, esto significa que los elementos de la colección tienen su propio orden específico según el cual están ordenados. Para una mejor comprensión, una colección que no está ordenada almacena sus elementos en orden aleatorio. Por ejemplo, Conjunto.

Ordenado:

Esto significa que un grupo de elementos se clasifica en una colección según los datos del elemento de la colección. Es decir, no sólo está ordenada la colección, sino que también el orden de los elementos depende de sus valores. Este orden puede cambiar si ordena por un valor de elemento diferente.

28. ¿Qué colecciones hay con una interfaz de Lista? ¿Cómo se trabaja con Lista?

Los valores de los elementos de una hoja se basan en su índice: están ordenados por índice. Se permiten repeticiones de elementos (es decir, puedes agregar el mismo objeto a la colección varias veces y estará bien).

Lista de arreglo:

La colección más común. Esencialmente, es una matriz con un tamaño que se expande dinámicamente. El trabajo de gestionar el tamaño de la matriz recae en la colección. Es importante que entendamos que en la mayoría de los casos esto es lo que necesitamos usar. Peculiaridades:
  • búsqueda rápida y búsqueda de índice rápida;
  • la colección está ordenada por índice, pero no ordenada;
  • implementa la interfaz RandomAccess;
  • agregando lentamente a la mitad de la lista.
Ejemplo:
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");
   }

}
>> salida

   [John, John, Roman, Ivan]
El resultado muestra que estos son elementos repetibles. Se muestran en el orden en que fueron grabados. ¿Qué más leer? Sí, hay mucha información, ni siquiera necesitas salir de JavaRush:

Lista enlazada:

Esta es una colección en la que cada elemento tiene un enlace al elemento anterior y siguiente. Estos enlaces le permiten pasar de un elemento a otro. Al agregar un elemento, los enlaces a los elementos anterior y siguiente simplemente cambian: Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core.  Parte 2 - 2
  • los elementos están conectados entre sí, es decir, se implementa una lista doblemente enlazada;
  • la velocidad general de operación es notablemente menor que en ArrayList;
  • una excelente opción para una gran cantidad de inserciones y eliminaciones en medio de una matriz;
  • implementa las interfaces de lista Queue y Deque y, por lo tanto, tiene sus métodos de trabajo.
Ejemplo:
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");

29. ¿Cuéntenos sobre la colección de mapas y sus implementaciones?

Map es una colección de valores clave. Hay una clave única y un valor que coincide con ese valor. equals()También se utilizan métodos hashcode()para determinar la unicidad de una clave.

Mapa Hash:

  • no clasificado ni ordenado;
  • se utiliza si el orden y la clasificación no son importantes;
  • admite clave nula.
Ejemplo:
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}
Las claves son siempre únicas, por lo que sólo se registra una persona mayor.

LinkedHashMap:

  • mantiene el orden de inserción;
  • más lento que HashMap;
  • Se espera que la iteración sea más rápida que en HashMap.
Ejemplo:
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}

Mapa de árbol:

Una implementación de mapa que mantiene las entradas ordenadas según el orden natural de sus claves, o mejor aún, usando un comparador si se proporciona uno en el constructor cuando se crea el mapa. Ejemplo:
  1. Sin comparador

    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. Con comparador

    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}
Vemos que la clasificación en orden ascendente se implementa como estándar, pero esto se puede cambiar agregando un comparador al constructor. TreeMap está bien descrito aquí .

30. ¿Cuéntenos sobre la colección Set y sus implementaciones?

Un conjunto es un conjunto de elementos únicos, y ésta es su característica principal. Es decir, Set no permite que se repitan los mismos elementos. Es importante aquí que los objetos que se agreguen tengan un método implementado equals .

Conjunto de hash:

  • no clasificado ni ordenado. Debajo del capó hay un HashMap con un marcador de posición para el valor. Ver por ti mismo ;)
  • usa hashCode para agregar objetos;
  • Debe usarse cuando se necesita tener objetos únicos y su orden no es importante.
Ejemplo:
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]
Aquí puede ver que el elemento "junior", que se agregó dos veces, está presente solo en una instancia. Y el orden no es el mismo que al sumar.

Conjunto de hash vinculado:

  • versión ordenada de HashSet;
  • mantiene una lista doblemente enlazada para todos los elementos;
  • Úselo cuando necesite orden en su iteración.
Ejemplo:
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]

Conjunto de árboles:

  • una de las dos colecciones ordenadas;
  • utiliza una estructura de árbol rojo-negro y garantiza que los elementos estén en orden ascendente;
  • Debajo del capó hay un TreeMap con un talón de los valores. Y los elementos del TreeSet son las claves del TreeMap (ver también;)).
Ejemplo:
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]

Excepciones

31. ¿Qué es la excepción?

La excepción es un problema que puede ocurrir en tiempo de ejecución. Esta es una situación excepcional que surge por algún motivo. El diagrama de herencia de excepciones se ve así (debe saberlo de memoria;)): Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core.  Parte 2 - 3El diagrama muestra que, en general, todas las excepciones se dividen en dos grupos: excepciones y errores. Error : las JVM se utilizan para mostrar errores después de los cuales la aplicación ya no tiene sentido. Por ejemplo, StackOverFlowError, que dice que la pila está llena y el programa ya no se puede ejecutar. Excepción : excepciones que se generan mediante programación en el código. Hay varias excepciones, marcadas y no marcadas, pero lo principal es que existen, se pueden detectar y la aplicación puede seguir funcionando. Las excepciones, a su vez, se dividen en aquellas que heredan de RuntimeException y otras descendientes de Exception. Hay suficiente información sobre este tema. Hablaremos sobre las excepciones marcadas y no marcadas a continuación.

32. ¿Cómo maneja la JVM las excepciones?

¿Cómo funciona? Tan pronto como se produce una excepción en algún lugar, el tiempo de ejecución crea un objeto de excepción (denotado como ExcObj). Almacena toda la información necesaria para el trabajo: la excepción en sí que se lanzó y el lugar donde ocurrió. La creación ExcObjy transmisión al tiempo de ejecución no es más que "lanzar una excepción". ExcObjcontiene métodos que se pueden usar para llegar al lugar donde se lanzó la excepción. Este conjunto de métodos se llama Call Stack. A continuación, el sistema de ejecución busca un método en la pila de llamadas que pueda manejar nuestra excepción. Si encuentra un controlador correspondiente, es decir, el tipo de excepción coincide con el tipo en el controlador, todo está bien. Si no lo encuentra, el tiempo de ejecución pasa todo al controlador de excepciones predeterminado, que prepara una respuesta y sale. Cómo se ve visualmente:
/**
* Пример, в котором показываются две опции — когда находится обработчик для исключения и когда нет.
*/
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";
       }
   }

   /**
    * Здесь две опции: o бросается {@link IOException} o {@link IllegalAccessException}.
    * Выбирается случайным образом.
    */
   private String randomThrower() throws IOException, IllegalAccessException {
       if (new Random().nextBoolean()) {
           throw new IOException();
       } else {
           throw new IllegalAccessException();
       }
   }
}
En nuestro caso, CallStack se verá esquemáticamente así:

randomThrower() => populateString() => main(String[] args)
Hay dos opciones: una u otra excepción se lanzará aleatoriamente. Para IOException todo está bien, si se genera, entonces el resultado del trabajo será: "Caught IOException". Pero si hay una segunda excepción para la cual no hay un controlador, el programa se detendrá con el siguiente resultado:

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. ¿Cómo manejan los programadores las excepciones?

En las preguntas anteriores ya se han utilizado ciertas palabras clave para trabajar con excepciones; ahora necesitamos hablar de ellas con más detalle. ¿Cuáles son las palabras clave?
  • intentar
  • atrapar
  • tirar
  • lanza
  • finalmente
Es importante tener en cuenta que atrapar, lanzar y lanzar solo se pueden usar con java.lang.Throwable. Esto no funcionará con otros tipos. Ahora discutiremos el intento, la captura y finalmente.
  • try-catch-finallyes una construcción que le permite detectar y manejar correctamente una excepción.
  • try- sólo puede haber un tiempo, ahí es donde ocurre la lógica;
  • catch— un bloque que recibe algún tipo de excepción; puede haber muchas. Por ejemplo, un bloque try generará varias excepciones que no tienen nada que ver entre sí;
  • finally- “finalmente” este bloque. Este es un bloque que se ejecutará en cualquier caso, independientemente de lo que se haga en try, catch.
Esto es lo que parece:
try {
   // сюда передают тот código, который может вызвать исключение.
} catch (IOException e) {
   // первый catch блок, который принимает IOException и все его подтипы(потомки).
   // Например, нет archivo при чтении, выпадает FileNotFoundException, и мы уже соответствующе
   // обрабатываем это.
} catch (IllegalAccessException e) {
   // если нужно, можно добавить больше одного catch блока, в этом нет проблем.
} catch (OneException | TwoException e) {
   // можно даже объединять несколько в один блок
} catch (Throwable t) {
   // а можно сказать, что мы принимаем ВСЁ))))
} finally {
   // этот блок может быть, а может и не быть.
   // и он точно выполнится.
}
Lea atentamente la descripción del ejemplo y todo quedará claro)

34. lanzar y lanzar en Java

tirar

throwse utiliza cuando necesita crear explícitamente una nueva excepción. Se utiliza para crear y lanzar excepciones personalizadas. Por ejemplo, excepciones relacionadas con la validación. Generalmente, para validación, heredan de RuntimeException. Ejemplo:
// пример пробрасывания исключения
throw new RuntimeException("because I can :D");
Es importante que esta construcción sólo pueda ser utilizada por algo que herede de Throwable. Es decir, no puedes decir esto:
throw new String("Cómo тебе такое, Илон Маск?");
A continuación, se finaliza el trabajo del hilo y comienza la búsqueda de un controlador que pueda procesarlo. Cuando no lo encuentra, va al método que lo llamó, y así la búsqueda irá subiendo por la línea de llamadas hasta que encuentre el controlador correspondiente o deje la aplicación ejecutándose. Miremos:
// Пример, который демонстрирует работу 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();
   }
}
Si ejecutamos el programa obtenemos el siguiente resultado:

Doing something
IOException was successfully handled.

lanza

throws— un mecanismo por el cual un método puede generar una o más excepciones. Se añaden separados por comas. Veamos que fácil y sencillo es:
private Object willThrow() throws RuntimeException, IOException, FileNotFoundException
Además, es importante tener en cuenta que puede haber excepciones marcadas y no marcadas. Por supuesto, no se pueden agregar excepciones no comprobadas throws, pero los buenos modales dicen lo contrario. Si se trata de elementos verificables, entonces, utilizando el método que los genera, deberá procesarlos de alguna manera. Hay dos opciones:
  1. Escriba try-catchcon la excepción de herencia apropiada y anterior.
  2. Úsalo throwsexactamente de la misma manera para que alguien más ya tenga este problema :D

35. Excepciones marcadas y no marcadas en Java

Hay dos tipos de excepciones en Java: marcadas y no marcadas.

Excepciones marcadas:

Estas son excepciones que se verifican en tiempo de compilación. Si algún código en un método arroja una excepción marcada durante una excepción, el método debe procesarlo usando try-catcho reenviarlo más. Por ejemplo, que lee una imagen de la ruta "/users/romankh3/image.png", la actualiza de alguna manera (para nosotros esto no es importante) y lo guarda.
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);
   }
}
Dicho código no se compilará, ya que los métodos estáticos ImageIO.read()generan ImageIO.write()una IOException, que se verifica y debe manejarse en consecuencia. Aquí hay dos opciones que ya hemos discutido anteriormente: usar try-catcho seguir adelante. Para una mejor asimilación, haremos esto y aquello. Es decir, updateAndSavesimplemente lo reenviaremos en el método y luego lo usaremos en el método principal 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);
   }
}

Excepciones no marcadas:

Estas son las excepciones que no se verifican en la etapa de compilación. Es decir, un método puede generar una RuntimeException, pero el compilador no le recordará que debe manejarlo de alguna manera. Como se muestra a continuación, tenemos todo lo que hereda de RuntimeException y Error sin marcar. Las 50 preguntas y respuestas principales de las entrevistas sobre Java Core.  Parte 2 - 4Considere el siguiente programa Java. El código se compila bien, pero genera una excepción cuando se ejecuta ArrayIndexOutOfBoundsException. El compilador le permite compilar porque ArrayIndexOutOfBoundsExceptiones una excepción no verificada. Una situación común con una matriz, que podría ser:
class CheckedImageExample {
   public static void main(String[] args) {
       int[] array = new int[3];
       array[5] = 12;
   }
}
El resultado será:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
  at main(CheckedImageExample.java:12)
Por cierto, ¿ya te has dado cuenta de que en Java nadie da nombres cortos? Cuanto más grande, mejor. Él, Spring Framework, tuvo mucho éxito en esto: solo tome alguna clase BeanFactoryPostProcessor )))

36. ¿Qué son las pruebas con recursos?

Este es un mecanismo mediante el cual todos los recursos deben cerrarse correctamente. De alguna manera no está claro, ¿verdad?) En primer lugar, qué es un recurso... Un recurso es un objeto, después de trabajar con el cual es necesario cerrarlo, es decir, llamar al close(). Un recurso son todos los objetos que implementan una interfaz AutoClosable, que a su vez implementa una interfaz Closeable. Es importante que comprendamos que todo InputStreames OutpuStreamun recurso y debe liberarse de manera correcta y exitosa. Esta es exactamente la razón por la que necesitamos utilizar try-with-resourcela estructura. Así es como se ve:
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) {
   // логика сохранения
}
En este ejemplo, el recurso es ZipInputStream, después de trabajar con el cual deberá cerrarlo. Y para no pensar en llamar al método close(), simplemente definimos esta variable en un bloque try, como se muestra en el ejemplo, y dentro de este bloque hacemos todo lo necesario. ¿Qué hace el ejemplo? Descomprimirá el archivo zip. Para hacer esto necesitas usar InputStream'om. Puede definir más de una variable; están separadas por un punto y coma. ¿Cuál es el problema? Pero se podría decir que puedes usar finallyun bloque. Aquí hay un artículo que detalla los problemas con este enfoque. También describe la lista completa de fallas que pueden ocurrirle a alguien que no utiliza este diseño. Recomiendo leerlo ;) En la parte final hay preguntas/respuestas sobre el tema de Multithreading. Mi perfil de GitHub
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION