Enum en Java

Estándar

El día de hoy tuve que lidiar con un nuevo tipo de dato en el lenguaje de programación Java: el tipo Enum.

Conociendo los enum

Según la documentación de Java sobre este tipo de dato, se dice que: “un tipo enum es un tipo de dato especial que permite a una variable ser un conjunto de constantes predefinidas”. En otras palabras, se podría decir que un tipo enum es un tipo de dato que el usuario define, el cual sólo puede tomar valores de una lista (véase lista como cualquier otra cosa menos un tipo List).

Y nos podemos preguntar: ¿para qué me serviría un enum? Bueno, respondo con preguntas: ¿cuántas veces necesitaste tener a la mano una lista de los días de la semana, los puntos cardinales?, ¿o alguna vez creaste un programa el cual trabaja con licencias, y quieres saber de qué tipo es la que tiene el usuario final? Bien, más claro no puedo decir: un tipo enum es un array de constantes, que tienen el mismo tipo que el enum.

¿Un ejemplo? Bien, hagamos un enum con los puntos cardinales:

package enums.punto;

public enum PuntoCardinal {
    NORTE,
    SUR,
    ESTE,
    OESTE
}

Ok, ese es un ejemplo simple. Y vemos algo nuevo: ya no tenemos nuestro “class”, en su lugar tenemos un “enum”. Deducimos entonces que un enum es una clase, así que debemos tratarla como tal. Ahora veamos cómo probarlo:

package enums.punto;

public class PruebaEnumPuntoCardinal {
    
    public static void main(String[] args) {
        
        PuntoCardinal p = PuntoCardinal.SUR;
        
        // Forma fácil de hacerlo, son constantes
        if (p == PuntoCardinal.SUR) {
            System.out.println("Perú queda en el SUR.");
        }
        
        // Forma POO para trabajar
        if (PuntoCardinal.SUR.equals(p)) {
            System.out.println("Perú queda en el SUR.");
        }
        
    }
    
}

Como podremos ver, podemos usar la POO para comprobar valores enum, o sino lo que aprendimos mucho antes y vemos en cualquier lenguaje: nuestro querido “==” 🙂

Un enum no es instanciable

Perfecto, pero ahora queremos hacer algo mucho más robusto, pues no es divertido aprender los puntos cardinales con Java. Entonces, ¿qué tal si asignamos un número a cada día de la semana?

package enums.semana;

public enum DiaSemana {
    
    DOMINGO(0),
    LUNES(1),
    MARTES(2),
    MIERCOLES(3),
    JUEVES(4),
    VIERNES(5),
    SABADO(6);
    
    public final int nroDia;
    
    private DiaSemana(int nroDia) {
        this.nroDia = nroDia;
    }
    
    public int getNroDia() {
        return nroDia;
    }
    
    public String getNombreDia() {
        return name();
    }
    
}

Según el código, podemos observar que a pesar que un enum es una clase, no es instanciable. Por lo tanto, si deseas prueba a hacer un “new DiaSemana(4)” y no podrás. Luego, otra pregunta que puede surgir es: ¿dónde declaraste el método name() al que llamas desde getNombreDia()? Mi respuesta es que todo enum hereda de la clase Enum, y viendo en la documentación de Java sabremos más. Bueno, probemos el código anterior:

package enums.semana;

public class PruebaEnumDiaSemana {
    
    public static void main(String[] args) {
        
        DiaSemana d = DiaSemana.DOMINGO;
        
        StringBuilder sb = new StringBuilder();
        sb.append("Hoy es ");
        sb.append(d.getNombreDia());
        sb.append(" y es número ");
        sb.append(d.getNroDia());
        sb.append(".");
        
        System.out.println(sb);
        
    }
    
}

Métodos heredados de Enum

Como ya dije antes, todo tipo enum hereda de la clase Enum de Java. Los métodos que hereda de ella son:

  • public final boolean equals(Object other): Devuelve TRUE si el objeto especificado es igual a esta constante. Sobrescribe el método “equals” de Object.
  • public final String name(): Devuelve en nombre de esta constante, tal y como fue declarada.
  • public final int ordinal(): Devuelve la posición de la constante según la declaración de éstas. A la primera constante declarada se le asigna 0.
  • public String toString(): Devuelve lo mismo que name(), pero sobrescribe “equals” de Object.
  • public static enumConstant[] values(): Devuelve un array con las constantes declaradas.

El porqué hice esto

Me animé a leer esto luego de tener que lidiar con algún código sacado de Zend Studio 10.5, el cual expongo:

package com.zend.php.core.core.key;

public enum SKU {
    
    SUBSCRIPTION(1, "Zend Studio Subscription"),
    IBM(2, "Zend Studio Standard for IBM-I"),
    PERPETUAL(3, "Zend Studio Perpetual");
    
    public final int index;
    public final String description;
    
    private SKU(int index, String description) {
        this.index = index;
        this.description = description;
    }
    
    public static final SKU byIndex(int index) {
        SKU[] values = values();
        for (SKU sku : values) {
            if (sku.index == index) {
                return sku;
            }
        }
        return null;
    }
    
}

Y luego de ver un código tipo “parche” en el que el creador intentó igualar el enum con una clase, preferí aprender algo sobre los enum antes que igualarlo con clases.

Bien, eso ha sido todo. Como siempre, los archivos usados están en este link.

Solución a la práctica de Algoritmos I – Grupo A

Estándar

La práctica tomada por el profesor el día de hoy nos sorprendió un poco con el tiempo dado para resolverla. Aún así, logré ver que la mayoría logró resolverla en una escala media.

El trabajo que ahora tenemos consta en desarrollar la práctica. Y como es una oportunidad para mejorar lo que hicimos durante el tiempo dado, pues aquí expongo la mejora de mi código (el que hice en clase me lo reservo).

Codificación

public class Fraccion {
    
    private int num;
    private int den;
    
    /**
     * Crea una nueva Fraccion.
     */
    public Fraccion() {
        num = 0;
        den = 1;
    }
    
    /**
     * Copia la Fraccion en f a esta Fraccion.
     * @param f Fraccion a copiar
     */
    public Fraccion(Fraccion f) {
        num = f.num;
        den = f.den;
    }
    
    /**
     * Inicializa los valores de esta Fraccion.
     * @param num numerador
     * @param den denominador
     */
    public Fraccion(int num, int den) {
        this.num = num;
        this.den = den;
    }
    
    /**
     * Obtiene el numerador de esta Fraccion.
     * @return numerador
     */
    public int getNum() {
        return num;
    }
    
    /**
     * Obtiene el denominador de esta Fraccion.
     * @return denominador
     */
    public int getDen() {
        return den;
    }
    
    /**
     * Asigna el numerador de esta Fraccion.
     * @param num numerador a asignar
     */
    public void setNum(int num) {
        this.num = num;
    }
    
    /**
     * Asigna el denominador de esta Fraccion.
     * @param den denominador a asignar
     */
    public void setDen(int den) {
        this.den = den;
    }
    
    /**
     * Suma dos Fracciones.
     * @param f segunda Fraccion a sumar
     * @return Fraccion suma
     */
    public Fraccion sumar(Fraccion f) {
        return new Fraccion(num * f.den + f.num * den, den * f.den);
    }
    
    /**
     * Multiplica dos Fracciones.
     * @param f segunda Fraccion a multiplicar
     * @return Fraccion producto
     */
    public Fraccion multiplicar(Fraccion f) {
        return new Fraccion(num * f.num, den * f.den);
    }
    
    /**
     * Simplifica una Fraccion.
     * @return Fraccion simplificada
     */
    public Fraccion simplificar() {
        int n = num;
        int d = den;
        int res;
        // Calculamos el MCD
        while (d != 0) {
            res = n % d;
            n = d;
            d = res;
        }
        return new Fraccion(num / n, den / n);
    }
    
    /**
     * Compara fracciones.
     * @param f Fraccion a comparar
     * @return true si esta Fraccion es mayor a f.
     */
    public boolean esMayor(Fraccion f) {
        if (num * f.den > f.num * den) {
            return true;
        }
        return false;
    }
    
    /**
     * Devuelve la Fraccion como cadena.
     * @return Fraccion como String
     */
    public String toString() {
        return num + "/" + den;
    }
    
}
import java.util.Random;
import java.util.Scanner;

public class PruebaFraccion {
    
    private static void generar(Fraccion[] v) {
        Random r = new Random();
        for (int i = 0; i < v.length; i++) {
            int num = r.nextInt(10);
            int den = r.nextInt(10);
            // El denominador no puede ser 0
            while (den == 0) {
                den = r.nextInt(10);
            }
            v[i] = new Fraccion(num, den);
        }
    }
    
    private static void mostrar(Fraccion[] v) {
        System.out.println();
        for (int i = 0; i < v.length; i++) {
            // No es necesario llamar a toString()
            // pues lo llama de manera automatica
            System.out.println(v[i]);
        }
        System.out.println();
    }
    
    private static Fraccion mayor(Fraccion[] v) {
        Fraccion mayor = new Fraccion(v[0]);
        // i = 1 porque ya asignamos arriba
        // la fraccion mayor a 0
        for (int i = 1; i < v.length; i++) {
            if (v[i].esMayor(mayor)) {
                mayor = new Fraccion(v[i]);
            }
        }
        return mayor;
    }
    
    private static Fraccion suma(Fraccion[] v) {
        Fraccion suma = new Fraccion(v[0]);
        // i = 1 tambien
        for (int i = 1; i < v.length; i++) {
            suma = suma.sumar(v[i]);
        }
        return suma;
    }
    
    private static Fraccion producto(Fraccion[] v) {
        Fraccion producto = new Fraccion(v[0]);
        // i = 1 tambien
        for (int i = 1; i < v.length; i++) {
            producto = producto.multiplicar(v[i]);
        }
        return producto;
    }
    
    public static void main(String[] args) {
        
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Numero de elementos: ");
        int n = sc.nextInt();
        sc.close();
        
        Fraccion[] v = new Fraccion[n];
        
        generar(v);
        mostrar(v);
        
        // Tener en cuenta que el toString()
        // ya no debe ser llamado porque Java
        // automaticamente sabe llamarlo
        System.out.println("Fraccion mayor: " + mayor(v));
        System.out.println("Suma: " + suma(v).simplificar());
        System.out.println("Producto: " + producto(v).simplificar());
        
    }
    
}

Espero sus comentarios, observaciones, y otros 🙂

¿Por qué aprender a programar?

Estándar

Posiblemente hayas escuchado alguna vez hablar acerca de programación. Y también es probable que te hayas preguntado qué era eso, en qué consiste, o como otros usuarios, que te importa lo que sea, si al fin y al cabo no lo vas a usar.

Pues la intención de este artículo es explicar, como el título lo dice, el porqué aprender a programar. Y es que no podemos vivir en este siglo sin saber algo tan simple que implica programar.

Antes que nada, veamos a nuestro alrededor. Desde el momento en que estás leyendo este artículo, debes estar usando un dispositivo con conexión a Internet. ¿Y adivina qué? Tu dispositivo tiene un sistema operativo, sea de escritorio, móvil o propietario.

Y si te diste cuenta, ¡el sistema operativo viene programado! Sino, reflexiona unos segundos acerca de la pregunta: ¿cómo es que funciona mi dispositivo, respondiendo a las órdenes que le hago?. La respuesta es inmediata: programación.

Tal vez el sistema operativo nunca nos hable y diga: “soy un sistema operativo, y estoy programado en el lenguaje X”. Sé que no lo hará. Y es que los que los fabrican (si usas Windows, Microsoft; Android, Google; iOS, Apple; FirefoxOS, Mozilla, entre otros) saben que tú nunca lo querrás saber, y así les ahorras un gran trabajo de poner una opción más en su sistema que te informe en qué lenguaje de programación fue diseñado el sistema.

Algo que olvidé decir: un lenguaje de programación es un conjunto ordenado de instrucciones, que realizan tareas específicas de acuerdo a qué sea necesario hacer. En pocas palabras, usando un lenguaje de programación puedes crear programas, los que pueden ir desde muy simples, hasta la creación de grandes sistemas. Ejemplo de éstos tenemos: PHP (mi preferido), JavaScript (uno de los lenguajes más usados para web), HTML (no sé qué de lenguaje tenga esto además de un modelo de documento, pero según dicen, con el auge de HTML5, se ha convertido en un lenguaje de programación), CSS (muchos dirán que es similar a HTML, pero para mí despliega tu creatividad, y eso es algo esencial de un lenguaje de programación), Python (el mejor para los que desean iniciarse en programación, pero te acostumbra a malas prácticas), Ruby (uno de los más poderosos y potentes del mundo), C (el padre de todos los lenguajes), C++ y C# (variantes ligeras de C), Java (uno de los mejores en programación orientada a objetos, luego de SmallTalk), ASP (propiedad de Microsoft), entre otros.

Siguiendo con el tema de los sistemas operativos, ¿ahora crees que sea útil decir en qué lenguaje de programación fue programado algo? Si tu respuesta aún es no, no te preocupes, acaba de leer el artículo y de inmediato cambiarás de opinión 🙂

Todo en los ordenadores, en lo que nos rodea, se basa en lenguajes de programación. Incluso las aplicaciones que usamos casi a diario: Microsoft Word, Excel, Internet Explorer (mi más sentido pésame si aún lo usas), Mozilla Firefox (digno de admirar, en otro artículo explicaré el por qué), tu juego de Buscaminas (si lo jugaste alguna vez, sino ¡qué esperas!), y otras aplicaciones de uso diario. Ahora ¿ya crees que es útil saber en qué lenguaje están programados?

Bueno, si aún dices “no, pues: ¿qué pasaría si algún día quieres mejorar tus aplicaciones, dotarlas de funcionalidades propias que te hagan la vida más fácil de lo que ya es con los ordenadores, si quisieras crear algún virus para obtener las contraseñas de tu amigo (no tomes en cuenta esto, fue a modo de ejemplo)? Si no sabes programar, pues paga a un “especialista” que lo haga. Cuando lo hagas, comenta sólo cuánto te cobró, y si te desmayaste o no. ¡Merecemos aprender por nuestros propios medios! ¡Necesitamos hacer trabajar a los ordenadores para nosotros, no nosotros para ellos!

Ahora, piensa en esto: ¿no crees que sería un buen complemento para ti saber a programar? Sino piensa en las ventajas: dile  a tu amiga(o) que sabes programar y mañana tienes una boda. Sé que puedes estar más adelante de los que te rodean. Dichas personas “normales” que se pasan la vida usando programas ya hechos, y que cuando quieren una nueva característica, tienen que pedir soporte técnico para lograrlo.

Programar es algo muy bonito, te lo aseguro. Llevo 4 años de mi vida programando (desde mis 13), y la verdad es que me he quitado muchos problemas de encima fácilmente. ¿Cómo? Usando la lógica y la programación.

Mencioné “lógica” porque no puedes programar algo sin lógica. Sino ¿qué sería Word sin que sepa que cuando tú presiones la gran “N” es que quieres un texto en negrilla (o negrita, como le quieras llamar)? La lógica y la programación van completamente de la mano. Aprender a programar es fácil. Aprender a pensar lógicamente no. Esto implica un proceso más largo, el cual debes haberlo venido desarrollando desde que naciste, sin darte cuenta de ello.

¿Ya estás asustándote con lo tanto que parlo? Pues no te preocupes, aún te falta leer el triple de lo que llevas leído, aumentado en 2 palabras. Okay, no más lógica por hoy 🙂 No hay de qué temer, un ordenador nunca se levantará y te llevará de la nada a otro lugar. A menos que trabajes en inteligencia artificial.

Continuando con el tema de la programación, puedes ver mis experiencias como programador en esta página. Pregunto por tercera vez: ¿aún sigues creyendo que aprender a programar no te servirá de nada? ¡Pues pongamos un ejemplo! Estás en tu hogar, sin nadie de compañía. La luz se apaga. ¿Qué es lo primero que piensas? Si pensaste “se quemó la bombilla”, al igual que yo, pues estás a un paso de poder programar. Si pensaste algo más avanzado, no te preocupes, siempre hay personas raras, y son ellas las que más rápido pueden aprender a programar. ¿Otro ejemplo? Creo que ya eso fue suficiente.

Bien. Después de toda la introducción, pasemos a ver qué maravillas podrías hacer al programar. Si trabajas con programas de oficina, ¿no sería más fácil agregar un formato predefinido para cada tipo de documento que redactes? Si vas jugando todo el día, ¿y si crearas tu propio juego, el que tenga lo que tú deseas, en lugar de adaptarte a lo que te brinda determinado juego? Si estudias matemáticas, ¿influiría en algo que tuvieras un programa listo que graficara todas las funciones que desees, y así copiar o imprimir las gráficas hechas a tu manera? Si vendes productos, ¿sería mejor crear un programa que administrara eficientemente tus ventas? Si eres adicto a las redes sociales, ¿estoy en lo cierto que tener tu propia aplicación con las redes sociales que usas a diario sería lo mejor que podrías tener? Y así, puedo seguir dando muchos ejemplos.

Ahora, tengo otra buena noticia: ¡yo no crearé estos programas por ti! Y si lo hago, pues te cobro, pero no porque sepa más que tú, sino porque tu pereza no te deja hacerlo, y la pereza se paga de alguna manera. La información es gratis. Y si tampoco me crees, ¿por qué no buscas en Google (o en tu buscador favorito, yo recomiendo DuckDuckGo) información acerca de “Java”“iniciación a la programación”? Verás muchos resultados 🙂

Y para no hacer más larga la situación, te invito a que al menos intentes buscar información acerca de todo lo hablado aquí. Sería gratificante para mí que me comentaras qué lenguaje de programación hizo posible que estés leyendo este artículo. Que supieras que puedes crear juegos para móviles usando Java.

Espero haberte convencido de la importancia que tiene el aprender a programar. Y si no lo hice, pues pido disculpas por haberte hecho perder el tiempo leyendo esto. Aunque al menos agradece que se te fue la pereza.

Por cierto, si esto quedó muy corto, puedes contactarme directamente. Si deseas, en una próxima edición hago una iniciación a determinado lenguaje, o quizás ya me hayas ganado en la carrera del aprendizaje y quieras contribuir con esta página. ¡Buen día!

Separar palabras de una frase en Java

Estándar

Muchas veces nos vemos en la necesidad de separar una frase en palabras, para así poder comprobar con algún diccionario su correcta escritura, si son o no malas palabras, entre otros.

Java, por su parte, provee de muchas funciones para el tratamiento de esto. Dentro de ellas, podemos encontrar el método split de la clase String. También podemos hacerlo con expresiones regulares. Pero la verdad es que para los que somos principiantes en Java, nos es muy difícil conocer todo esto.

Es por ello, que aquí presento una forma simple de separar una frase en palabras, teniendo en cuenta las peculiaridades de una frase, y además pensando que la frase no contiene espacios por delante y por detrás. Si alguien logra mejorar esto, por favor publicarlo en los comentarios 🙂

package vectores;

import java.util.Scanner;

/**
 * Clase para separar palabras de una frase.
 * @author Bryan Horna <bryanjhv@gmail.com>
 *
 */
public class Separar {
	
	static Scanner sc = new Scanner(System.in); // El Scanner
	
	/**
	 * Separa la frase en palabras.
	 * @param s La cadena a separar.
	 * @return Cadena en partes.
	 */
	public static String[] separarFrase(String s) {
		int cp = 0; // Cantidad de palabras
		
		// Recorremos en busca de espacios
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == ' ') { // Si es un espacio
				cp++; // Aumentamos en uno la cantidad de palabras
			}
		}
		
		// "Este blog es genial" tiene 3 espacios y 3 + 1 palabras
		String[] partes = new String[cp + 1];
		for (int i = 0; i < partes.length; i++) {
			partes[i] = ""; // Se inicializa en "" en lugar de null (defecto)
		}
		
		int ind = 0; // Creamos un índice para las palabras
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == ' ') { // Si hay un espacio
				ind++; // Pasamos a la siguiente palabra
				continue; // Próximo i
			}
			partes[ind] += s.charAt(i); // Sino, agregamos el carácter a la palabra actual
		}
		return partes; // Devolvemos las partes
	}
	
	public static void main(String[] args) {
		
		System.out.print("Ingrese una frase: ");
		String frase = sc.nextLine(); // Guardamos la frase o texto
		
		String[] p = separarFrase(frase); // Separamos palabras
		
		for (int i = 0; i < p.length; i++) {
			System.out.println("Parte " + (i + 1) + ": " + p[i]); // Mostramos
		}
		
	}
	
}

Como siempre, puedes descargar este código completo desde aquí.

Histograma en Java

Estándar

Tras haber visto varios artículos por Internet, vi algunos interesantes acerca de cómo generar un histograma con asteriscos en Java.

La verdad me decepcioné demasiado al saber que no saben ni siquiera pensar para subir algún contenido. Sólo suben lo que piensan con un título sugestivo para así poder ganar un poco de dinero con las visitas en su blog. Parece que yo, sin ganar dinero, publico contenido de calidad antes que eso, que lo único que nos hace perder a la mayoría de estudiantes es tiempo.

En este artículo muestro el código de un programa que me pidieron en la Universidad, para generar un histograma básico mediante el ingreso y tratamiento de vectores.

Aquí expongo el código:

package vectores; // El paquete que estoy usando

import java.util.Scanner; // Para el ingreso de datos

public class Histograma {
	
	public static void generarV(int[] v) { // Generamos un vector
		for (int i = 0; i < v.length; i++) {
			v[i] = (int) (Math.random() * 101);
		}
	}
	
	public static void histogramaV(int[] v) { // Hace el histograma
		int[] rep = new int[v.length]; // Repeticiones
		for (int i = 0; i < v.length; i++) {
			int ca = 0; // Cantidad (frecuencia)
			for (int j = 0; j < v.length; j++) {
				if (v[i] == v[j]) {
					ca++;
				}
			}
			if (rep[i] == 0) { // Si aún no se ha repetido
				System.out.print(v[i] + ": ");
				for (int k = 0; k < ca; k++) {
					System.out.print("*"); // Un '*' por cada punto frecuencial
				}
				System.out.println();
			}
			for (int j = 0; j < v.length; j++) {
				if (v[i] == v[j]) {
					rep[j]++; // Si ya está visto esta parte
				}
			}
		}
	}
	
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in); // Creamos el ingreso de datos
		
		System.out.print("Cantidad de elementos: ");
		int n = sc.nextInt(); // Almacenamos cantidad de elementos

		int[] v = new int[n]; // Creamos el vector

		generarV(v); // Lo generamos
		
		histogramaV(v); // Mostramos el histograma
		
	}
	
}

Sé que al código le falta optimizar ciertos aspectos. Aquel que logre esto, puede publicarlo en los comentarios. Así contribuiría con todos los lectores 🙂
Por cierto, puedes descargar el código desde aquí (me brindas unos cuantos céntimos al hacer clic).