Análisis de Odnoklassniki en Joker 2019



Del 28 al 29 de octubre, Joker 2019 se celebró en San Petersburgo, la conferencia más grande y más intensa en la inmensidad de Rusia dedicada al desarrollo de Java. El evento se realizó por séptima vez y, como siempre, rompió el récord de asistencia, esta vez atrajo a más de 2000 especialistas.

Los compañeros de clase tradicionalmente participan en Joker como socios del evento. Este año, en nuestro stand, uno podría tratar de hacer frente a las famosas tareas "irresolubles" de los principales ingenieros de OK.RU. Los participantes de la conferencia que respondieron las preguntas correctamente recibieron premios.

Para ser justos, debo decir que de 1,000 folletos con las tareas que entregamos, se devolvieron menos de 100. Lo mejor fue la solución, que obtuvo 4.5 puntos de 5.

Publicamos tareas y sus soluciones para que pueda probar su fortaleza.

1. Enum heroica


El código fuente de un juego poco conocido reveló dicho código. ¿Cuál es la mala implementación de Group.of y cómo solucionarlo?

 enum Group { Few(1, 4), Several(5, 9), Pack(10, 19), Lots(20, 49), Swarm(50, Integer.MAX_VALUE); Group(int min, int max) { ... } public static Group of(int count) { for (Group group : Group.values()) { if (count >= group.min && count <= group.max) { return group; } } throw new IllegalArgumentException(); } } 

Solución
Si no habla de estilos de codificación, este fragmento tiene un inconveniente objetivo: un posible problema de rendimiento. Aunque la búsqueda lineal a menudo resulta ser un cuello de botella, en este caso no es así, porque esta enumeración tiene solo cinco elementos. Y lo que realmente puede afectar negativamente el rendimiento es la asignación excesiva de memoria al llamar a Group.values() . El problema es que el método de values() de enum siempre devuelve una nueva copia de la matriz, y HotSpot aún no puede optimizarlo. Una solución simple es hacer su propia copia de la matriz de values() e iterar sobre ella:

 private static final Group[] ALL_GROUPS = Group.values(); public static Group of(int count) { for (Group group : ALL_GROUPS) { .... } 


2. sueños


Java 13 ya se ha lanzado, y Nikolai todavía solo comprende transmisiones. Indique errores en el método que calcula la diferencia entre los elementos de flujo máximo y mínimo.

 int getDiameter(Stream<Integer> stream) { int min = stream.min(Integer::compare).get(); int max = stream.max(Integer::compare).get(); return max - min; } 

Solución
Las secuencias en Java suelen ser de una sola vez: la llamada a la segunda operación del terminal (en este caso, max ) fallará:

 java.lang.IllegalStateException: stream has already been operated upon or closed 

Además, min y max return Optional , la operación get() en la que se lanzará una NoSuchElementException para una secuencia vacía. Por lo tanto, es más correcto verificar isPresent() antes de llamar a get() o usar otros métodos Optional : o Else , o ElseThrow , etc.

Finalmente, el hecho de que la diferencia entre las dos int ya no puede caber en el int no escapará al desarrollador cuidadoso, y valdría la pena cambiar el tipo del valor de retorno a long .

3. Tampón seguro


ByteBuffer primitiva de sincronización de Java puede hacer get operaciones de put y get subprocesos sean seguras en un ByteBuffer genérico?

 final ByteBuffer buf = ByteBuffer.allocate(SIZE); int get(int offset) { return buf.get(offset); } void put(int offset, int value) { buf.putInt(offset, value); } 

Elija la opción más efectiva si sabe que hay muchos subprocesos y obtenga ejecuciones con mucha más frecuencia que la puesta.

  • sincronizado
  • Reentrantlock
  • ReentrantReadWriteLock
  • Stampedlock
  • Semáforo
  • Leer y escribir int en Java siempre es atómico

Solución
ReentrantReadWriteLock pide ReentrantReadWriteLock lector y escritor, y a menudo esta será una solución efectiva. Pero tenga en cuenta que en este caso, las operaciones get y put son muy simples: la probabilidad de que un put competitivo pueda interferir con get es pequeña, además, es menos probable que ocurran condiciones de put con las operaciones put. Por lo tanto, puede aplicar el mecanismo de bloqueo optimista que proporciona StampedLock .

StampedLock será más eficiente que ReentrantReadWriteLock debido al hecho de que, en caso de un éxito de ruta rápida optimista, las variables compartidas no se actualizan en absoluto, mientras que ReentrantReadWriteLock realiza al menos un CAS en el mejor de los casos.

4. Regalos


Ilya está desarrollando una vitrina de regalos en una red social. Ayúdelo a escribir el método add para una estructura que no contenga más de N de los regalos más nuevos. No se debe agregar un regalo si ya está presente, o si es más antiguo que el resto de N.

 interface Present { long getId(); Date getCreated(); } void add(Present p) { // Implement me } 

Solución
TreeSet o PriorityQueue naturalmente adecuado como una estructura de datos con el fin de agregar regalos de forma efectiva y eliminar el más antiguo, no peor que para O (log N). Todo el truco está solo en el comparador: no es suficiente comparar regalos solo con getCreated() , porque la fecha de creación no tiene que ser única. Por lo tanto, debe comparar primero getCreated() , luego getId() . Tal comparador asegurará tanto la unicidad de los elementos como el orden por fecha.

 TreeSet<Present> tree = new TreeSet<>( Comparator.comparing(Present::getCreated) .thenComparing(Present::getId)); 

Sigue siendo un asunto pequeño: al agregar un regalo, verifique que el tamaño no exceda N y, si es necesario, elimine el primer elemento más antiguo de la colección.

 void add(Present p) { if (tree.add(p) && tree.size() > N) { tree.pollFirst(); } } 


5. No esperarás


¿Por qué Julia nunca esperará el final de este programa?

 var executor = Executors.newFixedThreadPool(4); for (File f : File.listRoots()) { executor.submit(() -> f.delete()); } executor.awaitTermination(2, TimeUnit.HOURS); 

Solución
La documentación de awaitTermination sugiere que la solicitud de apagado debe preceder a la ejecución. Es simple: Julia olvidó llamar a ejecutor.shutdown () .

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


All Articles