Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Cola | Estructuras de Datos Adicionales
Estructuras de Datos en Java

bookCola

Hablemos de dos estructuras de datos bastante interesantes: Queue y Deque.

Cola

Empecemos con una "cola". Imagina una cola en una tienda durante una venta. Hay 10 personas; la primera persona está más cerca de las puertas de la tienda que las demás, y la 10ª persona está más lejos. Cuando la primera persona entra en la tienda, sale de la cola, con lo que desplaza toda la cola una persona hacia delante. La "cola" de Java funciona según un principio muy similar.

De esta forma, podemos implementar varios programas en los que la lógica de la cola esté bien pensada. Por ejemplo, implementar un tablero con planes y tareas.

Pero primero, echemos un vistazo a los métodos básicos para trabajar con una Queue.

La Queue es una interfaz de la que hereda la clase LinkedList, con la que ya estás familiarizado, así que usaremos esta implementación.

Nota

Nota que la implementación de una clase (como LinkedList) puede heredar de ciertas interfaces e implementar métodos de estas interfaces.

De esta forma, usamos la interfaz como tipo del objeto, pero la implementación del objeto será LinkedList porque es una implementación específica de este objeto. (Recuerda que no podemos crear objetos basados en una interfaz, ¿verdad?)

Ejemplo:

example.java

example.java

copy
1234
// `LinkedList` as implementation of the `List` interface: List<T> list = new LinkedList<>(); // `LinkedList` as implementation of the `Queue` interface: Queue<T> queue = new LinkedList<>();

De esta manera, podemos hacer que nuestra aplicación sea muy flexible utilizando varias implementaciones de la misma interfaz.

Pero volvamos a los métodos de trabajo con Queue.

Métodos

Algunos métodos clave de la interfaz de Cola son:

  • add(elemento): Añade un elemento a la cola, lanzando una excepción si la operación no es posible.
  • ofrecer(elemento): Añade un elemento a la cola, devolviendo trueen caso de éxito ofalse` en caso contrario.

Puedes observar que estos métodos esencialmente hacen lo mismo. Sin embargo, la diferencia clave es la seguridad del método offer. En caso de un elemento añadido incorrectamente, el método offer no lanzará una excepción y no detendrá la ejecución del programa.

Pero por el momento, esta característica no es de gran interés para nosotros, ya que una Queue normal no está limitada. Sin embargo, existe una estructura llamada BlockingQueue, que tiene una restricción en el número de elementos; en ese caso, estos métodos tendrán una diferencia notable.

Veamos un ejemplo:

main.java

main.java

copy
1234567891011121314
package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.add("One"); queue.add("Two"); queue.add("Three"); System.out.println("Queue: " + queue); } }

Como puedes ver, al utilizar el método add() e intentar añadir un elemento que no cabe en la cola, el programa lanza un error, terminando inesperadamente la ejecución. Intentemos la misma operación pero con un método más seguro - offer():

main.java

main.java

copy
1234567891011121314
package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); } }

Como puedes ver, ahora el elemento no se añadió a la cola, pero tampoco lanzó una excepción. Por lo tanto, podemos considerar que hemos manejado el error con elegancia. Podemos manejar las excepciones de otra forma usando una estructura como try-catch, pero eso lo discutiremos más adelante.

Nota

Estructuras de datos como BlockingQueue, BlockingDeque, y similares están en el paquete java.util.concurrent y se utilizan para programación multihilo. Aprenderemos sobre multihilos de Java en futuros cursos.

Pasemos a los siguientes métodos:

Métodos de eliminación

  • remove(): Elimina y devuelve el elemento del principio de la cola, lanzando una excepción si la cola está vacía.
  • poll(): Elimina y devuelve el elemento del principio de la cola, devolviendo null si la cola está vacía.

Estos métodos realizan precisamente la función como si la primera persona de la cola entrara en el almacén y saliera de la cola. Aquí es donde entra en juego el principio FIFO (First In, First Out). En otras palabras, el elemento que se añadió primero a la cola será el primero que se elimine.

Aquí, también puedes observar la diferencia entre estos dos métodos. El método poll() se utiliza más a menudo que el método delete() porque es más seguro y no lanza excepciones.

Veamos un ejemplo:

main.java

main.java

copy
123456789101112131415
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.remove(); queue.remove(); System.out.println("Queue after removal operation: " + queue); } }

Como puedes ver, el programa lanza una NoSuchElementException porque estamos intentando eliminar un elemento de una cola vacía. Para evitar esta excepción, es mejor utilizar el método poll():

main.java

main.java

copy
123456789101112131415
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.poll(); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Ahora, hemos eliminado con seguridad un elemento de la cola, y no se lanzó ninguna excepción cuando intentamos eliminar un elemento de una lista vacía. Genial.

La función poll() que devuelve null se puede utilizar, por ejemplo, en un bucle while(). Veamos un ejemplo:

main.java

main.java

copy
1234567891011121314151617181920
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.poll() != null) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }

De esta forma, podemos eliminar todos los elementos de la cola utilizando un bucle. ¡Recuerda que el primer elemento que entró en la cola es el eliminado! Por ejemplo, en el caso del ejemplo anterior, el elemento con el dato "Uno" fue eliminado primero. El principio FIFO se demuestra a continuación:

main.java

main.java

copy
123456789101112131415161718
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Genial, podemos pasar a los métodos que devuelven el primer y último elemento:

  • Elemento()`: Devuelve, pero no elimina, el elemento del principio de la cola, lanzando una excepción si la cola está vacía.
  • buscar()`: Devuelve, pero no elimina, el elemento del principio de la cola, devolviendo null si la cola está vacía.

Bueno, creo que no necesito explicar por tercera vez que usar el método peek() es mucho mejor, ya que es más seguro y no lanza una excepción.

Veamos un ejemplo de uso:

main.java

main.java

copy
12345678910111213141516
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); System.out.println("The first element in the queue: " + queue.peek()); System.out.println("Queue after the `peek()` method: " + queue); } }

Puedes combinar este método con otros métodos de cola. Por ejemplo, si tenemos una cola con cinco elementos y necesitamos eliminar todos los elementos hasta el cuarto(inclusive), veamos la implementación de dicha operación:

main.java

main.java

copy
123456789101112131415161718192021
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (!queue.peek().equals("Four")) { queue.poll(); } queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Usamos un bucle con una condición basada en el método peek(). Podemos optimizar significativamente este bucle utilizando el método contains(). Este método devuelve true si el elemento especificado está presente en la cola y false si no lo está.

Mejoremos el código anterior:

main.java

main.java

copy
1234567891011121314151617181920
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.contains("Four")) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }

Aquí, establecemos una única condición para el bucle while. Hemos conseguido eliminar todos los elementos hasta el elemento "Cuatro" incluido.

En los próximos capítulos, aprenderás sobre otra estructura de datos similar - Deque, y también escribirás tu propia implementación de una aplicación Gestor de Tareas.

1. ¿Qué es una Queue en Java?

2. ¿Qué interfaz representa una cola en Java Collections Framework?

3. ¿Para qué sirve el método offer() de la interfaz Queue?

4. ¿Qué hace el método poll() en la interfaz Queue?

5. ¿Qué clase del paquete java.util.concurrent de Java representa una cola de bloqueo limitada?

6. ¿Qué ocurre si intentas añadir un elemento a una cola llena utilizando el método add()?

question mark

¿Qué es una Queue en Java?

Select the correct answer

question mark

¿Qué interfaz representa una cola en Java Collections Framework?

Select the correct answer

question mark

¿Para qué sirve el método offer() de la interfaz Queue?

Select the correct answer

question mark

¿Qué hace el método poll() en la interfaz Queue?

Select the correct answer

question mark

¿Qué clase del paquete java.util.concurrent de Java representa una cola de bloqueo limitada?

Select the correct answer

question mark

¿Qué ocurre si intentas añadir un elemento a una cola llena utilizando el método add()?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 2. Capítulo 1

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Suggested prompts:

Can you explain more about the difference between add() and offer() methods?

How does the FIFO principle work in a real-world queue?

What are some practical uses of the Queue interface in Java?

Awesome!

Completion rate improved to 4

bookCola

Desliza para mostrar el menú

Hablemos de dos estructuras de datos bastante interesantes: Queue y Deque.

Cola

Empecemos con una "cola". Imagina una cola en una tienda durante una venta. Hay 10 personas; la primera persona está más cerca de las puertas de la tienda que las demás, y la 10ª persona está más lejos. Cuando la primera persona entra en la tienda, sale de la cola, con lo que desplaza toda la cola una persona hacia delante. La "cola" de Java funciona según un principio muy similar.

De esta forma, podemos implementar varios programas en los que la lógica de la cola esté bien pensada. Por ejemplo, implementar un tablero con planes y tareas.

Pero primero, echemos un vistazo a los métodos básicos para trabajar con una Queue.

La Queue es una interfaz de la que hereda la clase LinkedList, con la que ya estás familiarizado, así que usaremos esta implementación.

Nota

Nota que la implementación de una clase (como LinkedList) puede heredar de ciertas interfaces e implementar métodos de estas interfaces.

De esta forma, usamos la interfaz como tipo del objeto, pero la implementación del objeto será LinkedList porque es una implementación específica de este objeto. (Recuerda que no podemos crear objetos basados en una interfaz, ¿verdad?)

Ejemplo:

example.java

example.java

copy
1234
// `LinkedList` as implementation of the `List` interface: List<T> list = new LinkedList<>(); // `LinkedList` as implementation of the `Queue` interface: Queue<T> queue = new LinkedList<>();

De esta manera, podemos hacer que nuestra aplicación sea muy flexible utilizando varias implementaciones de la misma interfaz.

Pero volvamos a los métodos de trabajo con Queue.

Métodos

Algunos métodos clave de la interfaz de Cola son:

  • add(elemento): Añade un elemento a la cola, lanzando una excepción si la operación no es posible.
  • ofrecer(elemento): Añade un elemento a la cola, devolviendo trueen caso de éxito ofalse` en caso contrario.

Puedes observar que estos métodos esencialmente hacen lo mismo. Sin embargo, la diferencia clave es la seguridad del método offer. En caso de un elemento añadido incorrectamente, el método offer no lanzará una excepción y no detendrá la ejecución del programa.

Pero por el momento, esta característica no es de gran interés para nosotros, ya que una Queue normal no está limitada. Sin embargo, existe una estructura llamada BlockingQueue, que tiene una restricción en el número de elementos; en ese caso, estos métodos tendrán una diferencia notable.

Veamos un ejemplo:

main.java

main.java

copy
1234567891011121314
package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.add("One"); queue.add("Two"); queue.add("Three"); System.out.println("Queue: " + queue); } }

Como puedes ver, al utilizar el método add() e intentar añadir un elemento que no cabe en la cola, el programa lanza un error, terminando inesperadamente la ejecución. Intentemos la misma operación pero con un método más seguro - offer():

main.java

main.java

copy
1234567891011121314
package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); } }

Como puedes ver, ahora el elemento no se añadió a la cola, pero tampoco lanzó una excepción. Por lo tanto, podemos considerar que hemos manejado el error con elegancia. Podemos manejar las excepciones de otra forma usando una estructura como try-catch, pero eso lo discutiremos más adelante.

Nota

Estructuras de datos como BlockingQueue, BlockingDeque, y similares están en el paquete java.util.concurrent y se utilizan para programación multihilo. Aprenderemos sobre multihilos de Java en futuros cursos.

Pasemos a los siguientes métodos:

Métodos de eliminación

  • remove(): Elimina y devuelve el elemento del principio de la cola, lanzando una excepción si la cola está vacía.
  • poll(): Elimina y devuelve el elemento del principio de la cola, devolviendo null si la cola está vacía.

Estos métodos realizan precisamente la función como si la primera persona de la cola entrara en el almacén y saliera de la cola. Aquí es donde entra en juego el principio FIFO (First In, First Out). En otras palabras, el elemento que se añadió primero a la cola será el primero que se elimine.

Aquí, también puedes observar la diferencia entre estos dos métodos. El método poll() se utiliza más a menudo que el método delete() porque es más seguro y no lanza excepciones.

Veamos un ejemplo:

main.java

main.java

copy
123456789101112131415
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.remove(); queue.remove(); System.out.println("Queue after removal operation: " + queue); } }

Como puedes ver, el programa lanza una NoSuchElementException porque estamos intentando eliminar un elemento de una cola vacía. Para evitar esta excepción, es mejor utilizar el método poll():

main.java

main.java

copy
123456789101112131415
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.poll(); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Ahora, hemos eliminado con seguridad un elemento de la cola, y no se lanzó ninguna excepción cuando intentamos eliminar un elemento de una lista vacía. Genial.

La función poll() que devuelve null se puede utilizar, por ejemplo, en un bucle while(). Veamos un ejemplo:

main.java

main.java

copy
1234567891011121314151617181920
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.poll() != null) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }

De esta forma, podemos eliminar todos los elementos de la cola utilizando un bucle. ¡Recuerda que el primer elemento que entró en la cola es el eliminado! Por ejemplo, en el caso del ejemplo anterior, el elemento con el dato "Uno" fue eliminado primero. El principio FIFO se demuestra a continuación:

main.java

main.java

copy
123456789101112131415161718
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Genial, podemos pasar a los métodos que devuelven el primer y último elemento:

  • Elemento()`: Devuelve, pero no elimina, el elemento del principio de la cola, lanzando una excepción si la cola está vacía.
  • buscar()`: Devuelve, pero no elimina, el elemento del principio de la cola, devolviendo null si la cola está vacía.

Bueno, creo que no necesito explicar por tercera vez que usar el método peek() es mucho mejor, ya que es más seguro y no lanza una excepción.

Veamos un ejemplo de uso:

main.java

main.java

copy
12345678910111213141516
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); System.out.println("The first element in the queue: " + queue.peek()); System.out.println("Queue after the `peek()` method: " + queue); } }

Puedes combinar este método con otros métodos de cola. Por ejemplo, si tenemos una cola con cinco elementos y necesitamos eliminar todos los elementos hasta el cuarto(inclusive), veamos la implementación de dicha operación:

main.java

main.java

copy
123456789101112131415161718192021
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (!queue.peek().equals("Four")) { queue.poll(); } queue.poll(); System.out.println("Queue after removal operation: " + queue); } }

Usamos un bucle con una condición basada en el método peek(). Podemos optimizar significativamente este bucle utilizando el método contains(). Este método devuelve true si el elemento especificado está presente en la cola y false si no lo está.

Mejoremos el código anterior:

main.java

main.java

copy
1234567891011121314151617181920
package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.contains("Four")) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }

Aquí, establecemos una única condición para el bucle while. Hemos conseguido eliminar todos los elementos hasta el elemento "Cuatro" incluido.

En los próximos capítulos, aprenderás sobre otra estructura de datos similar - Deque, y también escribirás tu propia implementación de una aplicación Gestor de Tareas.

1. ¿Qué es una Queue en Java?

2. ¿Qué interfaz representa una cola en Java Collections Framework?

3. ¿Para qué sirve el método offer() de la interfaz Queue?

4. ¿Qué hace el método poll() en la interfaz Queue?

5. ¿Qué clase del paquete java.util.concurrent de Java representa una cola de bloqueo limitada?

6. ¿Qué ocurre si intentas añadir un elemento a una cola llena utilizando el método add()?

question mark

¿Qué es una Queue en Java?

Select the correct answer

question mark

¿Qué interfaz representa una cola en Java Collections Framework?

Select the correct answer

question mark

¿Para qué sirve el método offer() de la interfaz Queue?

Select the correct answer

question mark

¿Qué hace el método poll() en la interfaz Queue?

Select the correct answer

question mark

¿Qué clase del paquete java.util.concurrent de Java representa una cola de bloqueo limitada?

Select the correct answer

question mark

¿Qué ocurre si intentas añadir un elemento a una cola llena utilizando el método add()?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 2. Capítulo 1
some-alt