OpenWebinars

Lenguajes de Programación

Introducción a Java: Estructuras de datos

¿Sabes por qué las estructuras de datos son como un andamio oculto que sostiene todo lo demás? En este artículo introductorio a Java, podrás conocer por qué estas herramientas son esenciales para la creación de software sólido y eficiente.

Alfredo Barragán

Alfredo Barragán

Experto Full Stack con PHP y JavaScript

Lectura 5 minutos

Publicado el 9 de octubre de 2023

Compartir

Introducción

¿Alguna vez te has preguntado cómo los datos se organizan y manipulan en Java?

Siguiendo nuestra serie de artículos introductorios sobre el lenguaje Java, hoy te hablaremos sobre su capacidad para manejar eficientemente grandes cantidades de datos mediante diversas estructuras de datos.

En este artículo abordaremos qué son las estructuras de datos y por qué son cruciales en Java, los diferentes tipos de estructuras de datos disponibles, y proporcionaremos ejemplos prácticos para cada uno de ellos.

Si no has leído previamente los artículos anteriores, te recomendamos echarles un vistazo, tanto al primero, Qué es Java: Introducción y primeros pasos, como al segundo, Introducción a Java: Datos y variables.

No pierdas detalle, ya que este es uno de los aspectos más importantes de Java, y la elección determinará el comportamiento en términos de rendimiento y usabilidad de tu aplicación.

Qué son las estructuras de datos en Java

Las estructuras de datos son elementos fundamentales en la programación que permiten almacenar y organizar datos de una forma eficiente. En Java, las estructuras de datos son utilizadas para almacenar, manipular y acceder a información de diversas formas. Estas estructuras actúan como cimientos sobre los cuales se construyen aplicaciones y algoritmos. La elección de una determinada estructura de datos permite a los programadores gestionar datos de manera eficaz, así como optimizar la memoria y recursos del servidor o PC en la que es ejecutada.

Estas herramientas son esenciales en el desarrollo de aplicaciones y algoritmos, ya que proporcionan la base sólida sobre la cual se construyen las aplicaciones informáticas. A través de estas estructuras, los programadores tienen la capacidad de gestionar datos de manera eficaz, permitiendo un acceso y manipulación versátiles para abordar una amplia gama de problemas y aplicaciones.

Un ejemplo muy sencillo de una estructura de datos, sería:

import java.util.HashMap;
import java.util.Map;

public class AlumnosNotas {
    public static void main(String[] args) {
     // Crear un HashMap para almacenar notas de alumnos
     Map<String, Double> notasAlumnos = new HashMap<>();

     // Agregar datos al HashMap
     notasAlumnos.put("Juan", 8.5);
     notasAlumnos.put("María", 9.0);
     notasAlumnos.put("Pedro", 7.5);
     notasAlumnos.put("Luisa", 8.0);
     notasAlumnos.put("Ana", 9.5);

     // Acceder a las notas de los alumnos
     double notaMaria = notasAlumnos.get("María");
     double notaPedro = notasAlumnos.get("Pedro");

     System.out.println("La nota de María es: " + notaMaria);
     System.out.println("La nota de Pedro es: " + notaPedro);

     // Modificar la nota de un alumno
     notasAlumnos.put("Pedro", 8.2); // Actualizamos la nota de Pedro

     // Imprimir todas las notas de los alumnos
     System.out.println("Notas de los alumnos:");
     for (Map.Entry<String, Double> entry : notasAlumnos.entrySet()) {
     String nombre = entry.getKey();
     double nota = entry.getValue();
     System.out.println(nombre + ": " + nota);
     }
    }
}

En este ejemplo, pensado para la administración de notas de un centro escolar, creamos una estructura de datos conocida como HashMap, con el nombre de notasAlumnos que almacena pares clave-valor, donde la clave es el nombre del alumno (una cadena) y el valor es la nota del alumno (un número decimal). Luego, agregamos algunos datos de ejemplo al HashMap, accedemos a las notas de algunos alumnos y también modificamos la nota de un alumno existente. Finalmente, iteramos a través de la estructura HashMap para imprimir todas las notas de los alumnos.

Conviértete en un Backend Developer
Domina los lenguajes de programación más demandados. Accede a cursos, talleres y laboratorios para crear proyectos con Java, Python, PHP, Microsoft .NET y más
Comenzar gratis ahora

Importancia de las estructuras de datos

Como hemos comentado, la elección adecuada de una estructura de datos es uno de los aspectos cruciales a la hora de diseñar nuestra aplicación, ya que puede marcar la diferencia entre una aplicación eficiente y una que consuma recursos innecesarios. Para ello, debes comprender que las estructuras de datos son esenciales por los siguientes motivos:

  • Optimización del rendimiento: Las estructuras de datos adecuadas pueden mejorar significativamente el rendimiento de una aplicación, reduciendo el tiempo de búsqueda y manipulación de datos.
  • Organización de datos: Ayudan a organizar datos de manera lógica y coherente, lo que facilita el acceso y la manipulación de la información.
  • Reutilización de código: Las estructuras de datos bien diseñadas permiten la reutilización de código, lo que ahorra tiempo y esfuerzo en el desarrollo de software.
  • Facilitar la resolución de problemas: Algunos problemas son más fáciles de resolver utilizando estructuras de datos específicas. Una elección adecuada puede simplificar la resolución de problemas complejos.

Tipos de estructuras de datos en Java

Java ofrece una variedad de estructuras de datos para satisfacer diferentes necesidades de programación.

Te presentamos algunas de las estructuras de datos más comunes en Java, podrás observar como algunas son comunes a otros lenguajes de programación y otras son específicas de este lenguaje:

Arrays

Los arrays, o arreglos, son colecciones de elementos del mismo tipo, accesibles a través de un índice. Son estáticos en tamaño, lo que significa que su tamaño no puede cambiar después de la creación.

Como es un tema que trae de “cabeza” a los programadores, te ilustro una de las formas en las que puedes modificar el tamaño de un Array, en caso de que sea necesario:

public class AumentarTamañoArreglo {
    public static void main(String[] args) {
     // Crear un arreglo inicial
     int[] arregloOriginal = {1, 2, 3, 4, 5};

     // Nuevo tamaño deseado para el arreglo
     int nuevoTamaño = 8;

     // Crear un nuevo arreglo con el nuevo tamaño
     int[] nuevoArreglo = new int[nuevoTamaño];

     // Copiar los elementos del arreglo original al nuevo arreglo
     for (int i = 0; i < arregloOriginal.length; i++) {
     nuevoArreglo[i] = arregloOriginal[i];
     }

     // Ahora tienes un nuevo arreglo con un tamaño mayor
     arregloOriginal = nuevoArreglo;

     // Puedes imprimir el nuevo arreglo
     for (int elemento : arregloOriginal) {
     System.out.print(elemento + " ");
     }
    }
}

Conjuntos

Los conjuntos son colecciones que no permiten elementos duplicados. HashSet y TreeSet son ejemplos de conjuntos en Java.

Son ideales cuando necesitas garantizar la unicidad de los elementos, pero debes tener cuidado pues si ya existe ese elemento debes controlar la excepción que lanza durante una operación de inserción.

Mapas

Estas estructuras de datos almacenan datos en forma de pares clave-valor, lo que facilita la búsqueda y recuperación eficiente de valores mediante una clave única.

Ejemplos de mapas en Java incluyen las clases HashMap y TreeMap.

Colas

Las colas siguen el principio “FIFO” (primero en entrar, primero en salir). Pueden ser implementadas como PriorityQueue o LinkedList.

Son útiles en situaciones donde el orden de llegada es relevante, el ejemplo típico, es la cola de tareas de la bandeja de impresión.

Pilas

Este tipo de estructura siguen el principio “LIFO” (último en entrar, primero en salir). La clase Stack en Java es un ejemplo de una pila.

Es útil para tareas como el procesamiento de expresiones matemáticas o en la ejecución de programa de terceros en la que es necesario gestionar dependencias de terceros.

Árboles

Son estructuras de datos jerárquicas que se utilizan para organizar datos de manera eficiente. Los árboles binarios, como el árbol de búsqueda binaria, son ejemplos comunes en Java y son esenciales en algoritmos de búsqueda y ordenación.

Son indicados para grandes conjuntos de datos donde la consulta necesita de grandes recursos.

Grafos

Los grafos son estructuras de datos utilizadas para representar relaciones entre elementos.

Aunque Java no proporciona una implementación directa de grafos, es posible construir o simular grafos utilizando otras estructuras de datos, como mapas o listas de adyacencia.

Matrices

Son colecciones bidimensionales de elementos del mismo tipo. Son útiles para almacenar datos en forma de tablas y se acceden mediante índices de fila y columna, lo que hace la operación de consulta muy rápida.

Colecciones

La interfaz Collection es la raíz de muchas estructuras de datos en Java y proporciona métodos comunes para operar en colecciones. Esto incluye operaciones como agregar, eliminar, buscar y recorrer elementos en una colección.

Estos tipos de datos y estructuras proporcionan a los programadores de Java las herramientas necesarias para abordar una amplia variedad de problemas y escenarios de programación de manera eficiente y organizada.

Ejemplos prácticos con estructuras de datos

A continuación, ilustraremos con ejemplos prácticos de cómo utilizar algunas de estas estructuras de datos en Java:

- Ejemplo con un array

En este ejemplo tenemos un array de números, que iteramos y mostramos el resultado por pantalla.

int[] numeros = {1, 2, 3, 4, 5};
for (int num : numeros) {
 System.out.println(num);
}

- Ejemplo con ArrayList

Este es un ejemplo de ArrayList de Strings, que contiene el nombre una serie de nombres, mostrando la operación de añadir y obtener la salida de los elementos:

ArrayList<String> nombres = new ArrayList<>();
nombres.add("Juan");
nombres.add("María");
nombres.add("Pedro");
System.out.println(nombres);

- Ejemplo con HashMap

Ejemplo de estructura de datos de un HashMap, en la que la clave es de tipo literal y el valor es tipo numérico.

HashMap<String, Integer> edades = new HashMap<>();
edades.put("Juan", 25);
edades.put("María", 30);
edades.put("Pedro", 22);
System.out.println(edades.get("María"));

Matriz bidimensional
public class EjemploMatriz {
    public static void main(String[] args) {
     int[][] matriz = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
     System.out.println(matriz[1][1]); // Imprime 5
    }
}

- Ejemplo con un grafo

Un grafo es una estructura de datos que consta de nodos (vértices) y aristas (conexiones entre los nodos). En Java, puedes implementar un grafo utilizando varias estructuras de datos, como listas de adyacencia o matrices de adyacencia.

Aquí te muestro un ejemplo de cómo crear un grafo utilizando una lista de adyacencia en Java:

import java.util.*;

// Clase para representar un grafo no dirigido utilizando una lista de adyacencia
class Grafo {
    private int V; // Número de vértices
    private LinkedList<Integer>[] listaAdyacencia; // Lista de adyacencia para almacenar las conexiones

    // Constructor para inicializar el grafo con un número dado de vértices
    public Grafo(int v) {
     V = v;
     listaAdyacencia = new LinkedList[v];
     for (int i = 0; i < v; ++i) {
     listaAdyacencia[i] = new LinkedList<>();
     }
    }

    // Método para agregar una arista al grafo
    public void agregarArista(int v, int w) {
     listaAdyacencia[v].add(w);
     listaAdyacencia[w].add(v);
    }

    // Método para imprimir el grafo
    public void imprimirGrafo() {
     for (int i = 0; i < V; ++i) {
     System.out.println("Lista de adyacencia del vértice " + i);
     System.out.print("Vértice " + i);
     for (Integer nodoAdyacente : listaAdyacencia[i]) {
      System.out.print(" -> " + nodoAdyacente);
     }
     System.out.println("\n");
     }
    }
}

public class EjemploGrafo {
    public static void main(String[] args) {
     Grafo grafo = new Grafo(5); // Crear un grafo con 5 vértices

     // Agregar aristas al grafo
     grafo.agregarArista(0, 1);
     grafo.agregarArista(0, 4);
     grafo.agregarArista(1, 2);
     grafo.agregarArista(1, 3);
     grafo.agregarArista(1, 4);
     grafo.agregarArista(2, 3);

     // Imprimir el grafo
     grafo.imprimirGrafo();
    }
}

- Ejemplo con una colección

Este es un ejemplo de una estructura de tipo colección utilizando la interfaz ArrayList, que es una implementación común de una lista dinámica:

ArrayList<Integer> numeros = new ArrayList<>();

 // Agregar elementos a la colección
 numeros.add(10);
// Acceder a elementos de la colección por índice
 int primerNumero = numeros.get(0);

// Modificar un elemento en la colección
 numeros.set(1, 25);
 // Eliminar un elemento de la colección
 numeros.remove(3);

- Ejemplo con una pila

En este ejemplo implementamos una estructura de tipo Pila a partir de la clase Stack, se realizan operaciones como inserción o la obtención de elementos.

Stack<String> pila = new Stack<>();

 // Agregar elementos a la pila
 pila.push("A");
 pila.push("B");
 pila.push("C");

 // Imprimir la pila
 System.out.println("Contenido de la pila: " + pila);

 // Obtener y eliminar el elemento en la cima de la pila
 String elementoCima = pila.pop();
 System.out.println("Elemento en la cima de la pila: " + elementoCima);
 System.out.println("Contenido de la pila después de pop: " + pila);

 // Verificar si la pila está vacía
 boolean estaVacia = pila.isEmpty();
 System.out.println("¿La pila está vacía? " + estaVacia);

- Ejemplo con una cola

Esta estuctura de datos se caracteriza por seguir con el princpio LIFO, el último elemento en entrar es el primero en salir, mediante la implementación de este ejemplo podemos observar su comportamiento.

import java.util.LinkedList;
import java.util.Queue;

public class EjemploCola {
    public static void main(String[] args) {
     Queue<String> cola = new LinkedList<>();

     // Agregar elementos a la cola
     cola.offer("X");
     cola.offer("Y");
     cola.offer("Z");

     // Imprimir la cola
     System.out.println("Contenido de la cola: " + cola);

     // Obtener y eliminar el elemento al frente de la cola
     String elementoFrente = cola.poll();
     System.out.println("Elemento al frente de la cola: " + elementoFrente);
     System.out.println("Contenido de la cola después de poll: " + cola);

     // Verificar si la cola está vacía
     boolean estaVacia = cola.isEmpty();
     System.out.println("¿La cola está vacía? " + estaVacia);
    }
}

Mejora las habilidades de tus desarrolladores
Acelera la formación tecnológica de tus equipos con OpenWebinars. Desarrolla tu estrategia de atracción, fidelización y crecimiento de tus profesionales con el menor esfuerzo.
Solicitar más información

Conclusiones

La elección de la estructura de datos adecuada puede mejorar significativamente el rendimiento y la eficiencia de una aplicación. Por ello, es esencial comprender en profundidad los tipos de estructuras de datos disponibles en Java y cómo utilizarlos de manera efectiva en tus proyectos.

A medida que la tecnología avanza, las tendencias futuras en el manejo de datos en Java pueden incluir la adopción de estructuras de datos más eficientes y la optimización de algoritmos para un rendimiento aún mejor. Además, debes saber que, con la integración de técnicas de inteligencia artificial y aprendizaje automático, estas estructuras de datos pueden migrar a otras más especializadas. Por tanto, debes estar atento a futuras implementaciones y actualizaciones.

Bombilla

Lo que deberías recordar de las estructuras de datos en Java

  • Las estructuras de datos son fundamentales en la programación en Java y son cruciales para el rendimiento de las aplicaciones.
  • Java ofrece una variedad de estructuras de datos, incluyendo arrays, listas, conjuntos, mapas, colas, pilas, árboles, grafos y matrices.
  • La elección de la estructura de datos adecuada depende de los requisitos específicos de tu proyecto.
  • Debes realizar un trabajo previo de requisitos y requerimientos de tu aplicación para realizar la mejor adopción de estructuras de datos, que de ellas depende en gran medida el rendimiento y eficiencia de la misma.
Compartir este post

También te puede interesar

Icono de la tecnología
Curso

Java desde 0: Orientación a Objetos

Principiante
6 h. y 41 min.

En esta formación veremos como crear una aplicación Java utilizando el paradigma de Orientación a Objetos, conociendo las...

Luis Miguel López Magaña
4.6