jueves, 10 de julio de 2014

Uso básico del BufferedReader

Las instancias (objetos) de la clase BufferedReader te permiten hacer lecturas sencillas desde flujos de caracteres, dentro de este post verás ejemplos sencillos de algunas formas de instanciar la clase y el uso de algunos de los métodos (los más relevantes según mi criterio) que trae consigo BufferedReader, tu tarea será darle un vistazo a aquellos que no se mencionen en este post, el contenido de la entrada será el siguiente:



1.- Definición

Como se mencionó antes BufferedReader es una clase cuyas instancias nos permiten hacer lecturas sencillas de texto desde un flujo de caracteres, debido a que esta clase trabaja con su propio buffer provee una lectura eficiente de caracteres, arreglos y líneas de texto. Otra ventaja de BufferedReader es que esta clase está sincronizada lo cual es sinónimo de seguridad al utilizarla en programación concurrente.

Volver al inicio ↑

2.- Ubicación

Primero que todo, esta clase se ubica en el paquete java.io por lo que en los códigos donde se utilice BufferedReader es necesario poner los siguientes import:

	import java.io.BufferedReader;
	import java.io.IOException;
			

Paréntesis: El último import es necesario puesto que al manejar BufferedReader manejamos FLUJOS por lo que se pueden presentar situaciones extraordinarias o también llamadas Excepciones un ejemplo de esto es que el flujo que estamos utilizando se cierre o sea modificado por un agente externo a nuestro programa.

Con el objetivo hacer más claro el funcionamiento de algunos métodos de BufferedReader agregaremos los siguientes imports al código:

	import java.io.FileReader;
	import java.io.InputStreamReader;
			

Volver al inicio ↑

3.- Creación de una instancia

Para instanciar la clase BufferedReader solo es necesario tener el flujo de caracteres del cual nuestra instancia, tomará hará las lecturas. La clase contiene dos constructores

BufferedReader(Reader in) BufferedReader(Reader in, int sz)

El primero únicamente requiere el flujo de caracteres que utilizará, en el segundo se puede especificar el tamaño del buffer que manejará. De presentarse el caso de que durante la ejecución del programa suceda que el tamaño del buffer que se haya especificado se quede corto para la cantidad de caracteres que tiene el flujo, no es problema, puesto que la misma instancia de BufferedReader se encarga de redimensionar el buffer al tamaño que sea necesario.

Aquí algunos ejemplos de cómo instanciar BufferedReader.

Instancia de BufferedReader que utiliza el flujo estándar asociado al teclado, este flujo es el que comúnmente se utiliza cuando se trabaja con consola.

	InputStreamReader flujo = new InputStreamReader(System.in);
	BufferedReader br = new BufferedReader(flujo);
			

Instancia de BufferedReader que utiliza el flujo estándar asociado al teclado, y cuyo tamaño de buffer se especificó de 1000 caracteres.

	InputStreamReader flujo = new InputStreamReader(System.in);
	BufferedReader br = new BufferedReader(flujo, 1000);
			

Instancia de BufferedReader que utiliza como flujo de caracteres un archivo de texto plano.

	FileReader flujo = new FileReader(“src/archivo.txt”);
	BufferedReader br = new BufferedReader(flujo);
			

Nota: Cuando se crea la instancia de FileReader es necesario que es su constructor se especifique la ruta relativa de la carpeta en que se encuentra el archivo, se puede asumir que en este ejemplo el archivo se encuentra en la misma carpeta donde se encuentra el código fuente del ejemplo.

Volver al inicio ↑

4.- Métodos

En la siguiente tabla se encuentran algunos de los métodos que se usarán en los ejemplos más adelante:

Método Tipo de Retorno Descripción
mark(int limiteCaracteres) void Marca la posición actual en la que se encuentre el apuntador en el flujo, el parámetro del método indica el número de caracteres que pueden ser leídos mientras se mantenga esta marca.
read() void Lee un solo carácter del flujo, lo curioso de este método es que retorna un número entero, ¿Por qué? Más adelante la respuesta.
readLine() String Lee una línea completa de texto.
ready() boolean Este método es utilizado para saber si aún hay caracteres en el flujo para ser leídos, detalles más adelante.
reset() void Reinicia el flujo hasta la marca más reciente que se haya hecho.
skip(long n) long Mueve el apuntador del flujo las posiciones necesarios para evitar la cantidad de caracteres de n.

Volver al inicio ↑

5.- Ejemplos

Aquí te presentamos ejemplos donde se utiliza de forma sencilla algunos métodos de BufferedReader, al final del post se anexa un enlace a algún servidor de archivos donde podrán descargar el código del ejemplo.

Nota: Dentro del código de los métodos presentados en todos los ejemplos se agrega lo siguiente throws IOException, pues con esto nos deshacemos de las excepciones de I/O que se puedan presentar durante la ejecución del programa, OJO dejar excepciones sin manejar nunca es una buena práctica de programación pero para los ejemplos nos es suficiente dejarlo así.

5.1.- Ejemplo 1: Lectura de un carácter método read().

Para este ejemplo utilizamos el método read() para la lectura de un solo carácter, como se mencionó en la sección anterior este método tiene algo curioso, su tipo de retorno es un int, - pero se supone que lee caracteres ¿WDF?-, bien esto se debe a que el valor entero que retorna es el valor de código ASCII que representa a ese carácter.

public static void lecturaChar() throws IOException {
	System.out.println(br.read());
}
					
				

Volver al inicio ↑

5.2.- Ejemplo 2: Lectura de un carácter método read() con casting.

Debido a que seguramente el código ASCII de un carácter no te es de mucha utilidad salvo en casos particulares (como que te encuentres en la Comunidad Estudiantil de Programación Competitiva), es necesario que le hagamos un casting de entero a carácter al valor que nos retorna el método read().

Paréntesis: Un cast o casting es forzar un tipo de dato para que sea tratado como otro tipo de dato COMPATIBLE, también se puede hacer casting a objetos de una clase para ser tratado como de otra clase. Este último procedimiento es comúnmente utilizado en Herencia y Polimorfismo.

public static void lecturaCharCasting() throws IOException {
	char caracter = (char) br.read(); //casting
	System.out.println(caracter);
}
					
				

Volver al inicio ↑

5.3.- Ejemplo 3: Lectura de caracteres hasta EOF.

En este ejemplo leemos caracteres hasta llegar al fin de archivo (EOF o End Of File) del flujo, para este ejemplo como flujo de entrada utilizamos un archivo de texto puesto que es más claro ejemplificar el EOF con archivos.

Paréntesis: El fin de archivo es un indicador cuya función es decir que se ha llegado al final del flujo y ya no hay más caracteres en él para ser leídos, el EOF de los archivos de texto plano es un -1 puesto que en el código ASCII no hay carácter alguno que posea un código negativo.

public static void lecturaChars() throws IOException{
	br = new BufferedReader(new FileReader("src/bufferedreader/texto_para_pruebas")) ;
	int codigo = br.read();
	char caracter;
        
	//mientras el código no sea -1 (EOF) continuo leyendo
	while (codigo != -1) { 
		caracter = (char) codigo; //casting
		System.out.print(caracter);
		codigo = br.read();
	}
}
					
				

Volver al inicio ↑

5.4.- Ejemplo 4: Lectura de una línea de texto.

El método readLine() como su nombre lo indica, nos permite hacer lectura de líneas completas de texto de nuestro flujo. A grandes rasgos el funcionamiento de este se basa en ir leyendo caracteres hasta encontrarse con el carácter ‘\n’ de salto de línea o ‘\r’ de retorno de carro, de esta forma BufferedReader sabe que ha terminado una línea y retorna los caracteres que leyó anteriormente.

En el código de ejemplo se agrega este String "(¬°o°)¬" al final del String leído por readLine() para hacer notar que se hizo la lectura.

public static void lecturaLinea() throws IOException{
	System.out.println(br.readLine()+"(¬°o°)¬");
}
					
				

Volver al inicio ↑

5.5.- Ejemplo 5: Lectura de líneas hasta EOF.

Similar al ejemplo 3 pero esta ocasión utilizando readLine() para la lectura de líneas completas. el concepto es similar pero la implementación es diferente.

public static void lecturaLineas() throws IOException{
	/*
	Si línea contiene null significa que se ha llegado al EOF, 
	es entonces cuando el ciclo termina.
	*/
	for(String linea = br.readLine(); linea != null; linea = br.readLine()){
		System.out.println(linea+"(¬°o°)¬");
	}
}
					
				

Volver al inicio ↑

5.6.- Ejemplo 6: Lectura de líneas hasta EOF método ready().

En el ejemplo anterior nosotros nos encargamos de programar la detección del EOF pero BufferedReader ya tiene un método definido para esto, ready(). El método ready() devuelve un valor booleano, true si aún hay caracteres en el flujo para leer y en caso contrario false.

public static void lecturaLineasPro() throws IOException{
	br = new BufferedReader(new FileReader("src/bufferedreader/texto_para_pruebas")) ;
	String linea;
	while (br.ready()) {//ready() retornará false cuando se llege al EOF
		linea = br.readLine();
		System.out.println(linea+"(¬°o°)¬");
	}
}

				

Volver al inicio ↑

5.7.- Ejemplo 7: Uso del método mark().

Tal vez mientras pensabas sobre la clase BufferedReader vino a tu mente la siguiente pregunta. ¿Qué pasa si quiero leer el contenido del flujo más de una vez?, cuando se presenta ese caso los métodos mark(long) y reset() son la solución. El método mark(long) establece una marca en la posición actual del apuntador del flujo de esta forma cuando se llame al método reset() regresará el apuntador a la última marca que haya sido hecha.

public static void lecturaConMarcado() throws IOException {
	br = new BufferedReader(new FileReader("src/bufferedreader/BufferedReaderEjemplo.java"));
	//se hace la marca al inicio de la lectura
	br.mark(100000);
	//lecturaLineas lee hasta EOF y termina su ejecución
	lecturaLineas();
	System.out.println("");
	//regresamos el apuntador del flujo al inicio que es donde hicimos la marca
	br.reset();
	//volvemos a leer todo el texto aún cuando ya se había llegado al EOF
	lecturaLineas();
}

				

Volver al inicio ↑

Código completo

A continuación te presentamos todo el código de ejemplo utilizado en el post, tambíen puedes descargar el proyecto en este enlace.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BufferedReaderEjemplo {

    public static BufferedReader br;

    public static void main(String[] args) throws IOException {
        InputStreamReader flujo = new InputStreamReader(System.in);
        br = new BufferedReader(flujo);

        //ejemplo 1 lectura de caracteres método read() (el método read lee los caracteres pero los interpreta en su código ASCII)
        lecturaChar();
        //ejemplo 2 lectura de caracteres método read() con casting a carácter
        lecturaCharCasting();
        //ejemplo 3 lectura de caracteres hasta EOF con método read()
        lecturaChars();
        //ejemplo 4 lectura de linea de texto
        lecturaLinea();
        //ejemplo 5 lectura de lineas hasta EOF
        lecturaLineas();

        //ejemplo 6 lectura de lineas hasta EOF con el método ready()
        lecturaLineasPro();
        //ejemplo 7 uso del método mark()
        lecturaConMarcado();
    }

    public static void lecturaChar() throws IOException {
        System.out.println(br.read());
    }

    public static void lecturaCharCasting() throws IOException {
        char caracter = (char) br.read(); //casting
        System.out.println(caracter);
    }

    public static void lecturaChars() throws IOException {
        br = new BufferedReader(new FileReader("src/bufferedreader/texto_para_pruebas"));
        int codigo = br.read();
        char caracter;

        //mientras el código no sea -1 (EOF) continuo leyendo carácteres
        while (codigo != -1) {
            caracter = (char) codigo; //casting
            System.out.print(caracter);
            codigo = br.read();
        }
    }

    public static void lecturaLinea() throws IOException {
        System.out.println(br.readLine() + "(¬°o°)¬");
    }

    public static void lecturaLineas() throws IOException {
        /*
         Si línea contiene null significa que se ha llegado al EOF, 
         es entonces cuando el ciclo termina.
         */
        for (String linea = br.readLine(); linea != null; linea = br.readLine()) {
            System.out.println(linea + "(¬°o°)¬");
        }
    }

    public static void lecturaLineasPro() throws IOException {
        br = new BufferedReader(new FileReader("src/bufferedreader/texto_para_pruebas"));
        String linea;
        while (br.ready()) {//ready() retornará false cuando se llege al EOF
            linea = br.readLine();
            System.out.println(linea + "(¬°o°)¬");
        }
    }

    public static void lecturaConMarcado() throws IOException {
        br = new BufferedReader(new FileReader("src/bufferedreader/BufferedReaderEjemplo.java"));
        //se hace la marca al inicio de la lectura
        br.mark(100000);
        //lecturaLineas lee hasta EOF y termina su ejecución
        lecturaLineas();
        System.out.println("");
        //regresamos el apuntador del flujo al inicio que es donde hicimos la marca
        br.reset();
        //volvemos a leer todo el texto aún cuando ya se había llegado al EOF
        lecturaLineas();
    }
}

				

Esperamos que el post te haya sido de ayuda, cualquier duda o comentario no dudes en hacérnoslo saber.

Volver al inicio ↑

6.- Referencias

Para más información sobre BufferedReader visita los siguientes enlaces:

Volver al inicio ↑

lunes, 30 de junio de 2014

La clase ArrayList.





Hay veces que estamos programando, y estamos usando arreglos con almacenamiento estático (un arreglo es un grupo de variables que contienen valores, todas de un mismo tipo) , el problema con ellos es precisamente ese, que su almacenamiento es estático,  ¿Qué quiere decir esto?, bueno que una vez que los declaramos, antes de usarlo, debemos definir cuál va a ser su tamaño, y este no podrá cambiar cuando el programa este corriendo, esto es un problema frecuente en  programación, y entonces me trae a la mente varias preguntas.

v  ¿Qué pasa si no sé cuál va a ser el tamaño del arreglo que quiero?
v  Tal vez si sepa el tamaño pero, ¿si necesito que crezca durante la ejecución del programa?
v  ¿Habrá implementaciones en Java que resuelvan este problema?

Bueno con un poco de suerte y podemos resolver todas estas cuestiones con un sola publicación así que manos a la obra, a continuación le presentare una clase interesante llamada ArrayList, esta supone una manera un poco distinta de trabajar a comparación de los arreglos normales, sobre todo porque este tipo de almacenamiento es dinámico, a medias, puesto que si no existieran y tuvieramos un arreglo normal en donde ya hemos ocupado toda su capacidad, lo que deberiamos hacer es crear otro arreglo con el doble de capacidad para poder copiar todo al arreglo nuevo y tener asi mas capacidad,y pues la clase ArrayList nos ahorra todo ese trabajo.

En publicaciones posteriores hablaremos de la clase LinkedList , la cual implementa una lista ligada y aunque su finalidad es la misma sus propiedades son un poco distintas.


¿Cómo la importamos?

import java.util.ArrayList;

ArrayList es una clase muy interesante de java, puesto que si uno se pone a pensar, nos ahorra mucho tiempo en cuestiones de implementación, es decir, un arrayList es un arreglo pero tiene la ventaja de que su almacenamiento es dinámico, y esto significa que su tamaño puede crecer o decrecer en tiempo de ejecución, algo que con un arreglo normal no se puede hacer.

Bueno todo esto está muy bien, pero lo que queremos es el código para aprender a usar un ArrayList , está bien comencemos con las declaraciones, ¿Cómo es que declaramos una ArraList?, debemos instanciar la clase ArrayList de la siguiente manera.


        ArrayList <String> cadena=new ArrayList();
       ArrayList <Integer> entero=new ArrayList();
       ArrayList <Double> flotante =new ArrayList();

**IMPORTANTE:: ArrayList No acepta como parámetro , tipos de datos abstractos(char,int,double,float,byte,short,long), en vez de eso debemos utilizar las clases adaptadas e estos tipos de datos (Integer para int ,String para char y String,Double para double,etc.) estas se comportan igual y tienen la ventaja de tener métodos de implementación que nos pueden servir, pero eso es tema de otra entrada.
Ademas esta es otra ventaja de arrayList, PODEMOS HACER ARRAYS DE CUALQUIER OBJETO QUE EXISTA EN JAVA.

En el ejemplo de arriba hemos declarado tres ArrayList de distintos tipos, ahora veamos como agregar elementos a ellos.

Para agregar elementos a ellos debemos usar el método add(); en cual le pasaremos como parámetro el elemento que queramos meter al ArrayList, es importante mencionar que este método esta sobrecargado, ¿Qué quiere decir esto?, bueno que dependiendo de lo que le pasemos como parámetro es como actuara y es que hay dos formas de este método, si solo le pasamos como parámetro el elemento que queremos agregar , lo agregara el final de la lista , pero si le pasamos como parámetros primero un número, y después separado por una coma el elemento a agregar , el método agregara el elemento en el índice del numero pasado.
 Forma 1
      cadena.add("HOLA");
       entero.add(1);
       flotante.add(2.3);
Para esta forma, el método agregara estos elementos en la posición final del ArrayList

Forma 2
       cadena.add(1,"HOLA");
       entero.add(1,1);
       flotante.add(1,2.3);

Para esta otra forma el método agregara el elemento que se la pasó en la posición del índice que le pasamos en el primer número que le dimos al elemento. En el caso de cadena “HOLA” será agregado en la posición 1, en el caso de entero (1) será agregado en la posición 1, y en el caso de flotante (2.3) será agregado en la posición 1.


**IMPORTANTE
Si usamos la segunda forma del add, si en la posición en la que le estamos indicando que insertaremos un elemento, ya existía algo, lo que hara es mover todos los elementos hacia adelante para que el nuevo pueda entrar, es decir no borra ningún elemento , solo los recorre, si lo que queremos es que borre el elemento que ya estaba , lo que debemos hacer es  usar el metodo set() explicado mas adelante.


Bueno bueno ya sabemos agregar elementos al ArrayList, ¿pero que hay si queremos obtener el valor de un elemento en el ArrayList?, si este es el caso entonces debemos usar otro método llamado get();,a este método basta con pasarle como parámetro el índice del elemento que queremos obtener , y el se encargara de obtenerlo y dárnoslo.
Por ejemplo si quisiéramos mostrar en consola los elementos que agregamos arriba, bastaría con hacer lo siguiente:

        System.out.println(cadena.get(1));
        System.out.println(entero.get(1));
        System.out.println(flotante.get(1));

Y el resultado obtenido seria el siguiente :
Resultado de imprimir la posición número 1 del Array





Bien estos dos métodos son básicos para empezar a usar los ArrayList, pero metámonos un poco más en los beneficios que nos da esta clase.
Hay más métodos que nos facilitan las cosas a la hora de programar, los siguientes son algunos de ellos.
isEmpty();
Devuelve true (verdadero) si es que el ArrayList que lo está llamando esta vacío.
contains(Object o);
Devuelve verdadero, si y solo si el elemento que se le pasa como parámetro se encuentra en el ArrayList, caso contrario devuelve falso.
indexOf(Object o);
Devuelve el índice de la primera ocurrencia del elemento pasado como parámetro, caso contrario devolverá un -1
lastIndexOf(Object o);
Devuelve el ultimo índice de las ocurrencias de elemento pasado como parámetro, caso contrario devolverá -1
remove(Object o);
remove (int index);
Este método actúa de acuerdo a lo que le pasemos como parámetro, es decir si le pasamos un objeto de la clase que es el ArrayList, lo buscara en el ArrayList y eliminara la PRIMERA ocurrencia de este y devolverá true, si no hay elemento devuelve false que significa que la lista no tenía ningún elemento como el que se le paso y por ende la lista no fue cambiada.

Sin embargo si le pasamos como parámetro un número, este lo tomara como un índice y eliminara lo que se encuentra en esa posición.
set(int index, Object o);
Define en el índice pasado como parámetro el objeto que también se pasó, es decir si le pasamos 1 , “hola”; pondrá en la posición 1 del ArrayList el texto hola, sin importar lo que haya ahí.
size();
Devuelve un entero con el tamaño del ArrayList.


Bien hasta ahora hemos visto muchos métodos que nos sirven para la clase ArrayList a continuación veremos un ejemplo, poniendo a prueba todo lo que hemos dicho hasta ahora.

   import java.util.ArrayList;

/**
 *
 * @author Luis
 */
public class ProbandoArrays {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        /**
         * Para esta prueba crearemos tres ArrayList
         */
        ArrayList cadena = new ArrayList();
        ArrayList entero = new ArrayList();
        ArrayList flotante = new ArrayList();
        /**
         * Una vez agregados llenaremos con diez posiciones cada uno el array de
         * String lo llenaremos con la forma HOLA X donde X es un número del 1
         * al 10 el array de enteros lo llenaremos con números del 1 al 10 y el
         * de flotantes lo llenaremos con números del 1.3 al 10.3 es importante
         * mencionar que el metodo add() agregará siempre al final de la lista
         */
        for (int i = 0; i <= 10; i++) {
            cadena.add("HOLA " + i);
            entero.add(i);
            flotante.add(i + 0.3);
        }

        //  Si quisieramos impimir el array completo haríamos lo siguiente 
        System.out.println(cadena);
        System.out.println(entero);
        System.out.println(flotante);

        // En cambio si ontener un elemento específico para usarlo o impimirlo
        //usaremos el método get();, imaginemos que queremos imprimir el elemento que esta
        // en la posición  4 de cada array, entonces debemos hacer lo siguiente
        System.out.println(cadena.get(4));
        System.out.println(entero.get(4));
        System.out.println(flotante.get(4));

        // algo importante es recordar que en los ArrayList los elmentos se empiezan
        //a contar desde la posicion 0.
        /**
         * ahora imagina que quieres agregar un elemento en una posicion
         * especifica del Array, bueno para eso existen dos métodos , y usaremos
         * el que nos convenga según el caso, si lo que queremos es insertar el
         * elemento en una posicion y queremos que los demás elementos se
         * recorran entonces usaremos el metodo add(indice,elemnto);, pero si lo
         * que queremos es agregar en una posicion el elmento y borrar lo que ya
         * había es esa posicion debemos usar el metodo set(indice,elemento);
         */
        System.out.println("\nAgregando un elemento en la posicion 5 y recorriendo todos los de más con el metodo add();");
        cadena.add(5, "Elemento agregado");
        entero.add(5, 9999);
        flotante.add(5, 333.44);
        System.out.println("Podemos ver que los elementos se recorrieron para dejar entrar al nuevo elemento\n");
        System.out.println(cadena);
        System.out.println(entero);
        System.out.println(flotante);

        System.out.println("\n Quitando el elemento de la posicion 2 con el método set();");
        cadena.set(2, "Eliminado y remplazado");
        entero.set(2, 000000000);
        flotante.set(2, .33333333333);
        System.out.println("El elemento fue remplazado, es decir eliminado, y cambiado por otro nuevo sin que los de más se recorrier\n");
        System.out.println(cadena);
        System.out.println(entero);
        System.out.println(flotante);

        /**
         * Que tal si queremos saber si existe algún elemento en la lista, con
         * una arreglo normal tendríamos que hacer un for e ir buscando el
         * elemento, ArrayList nos ahorra esto, o tan lo menos lo hace invisible
         * para nosotros y nos presenta el método contains(); , tenemos que
         * pasarle como parámetro el elemento a buscar , y nos devolvera true si
         * es que se encuentra y -1 o false si es que no esta el elemento
         */
        System.out.println("\n\nBucando elementos en el array con el metodo contains();");

        System.out.println("Buscamos en el array cadena la palabra HOLA 0 entonces nos devuleve: " + cadena.contains("HOLA 0"));
        System.out.println("Buscamos en el array cadena la palabra HOLA entonces nos devuleve: " + cadena.contains("HOLA"));

        System.out.println("\nBuscamos en el array entero el número 0 entonces nos devuleve: " + entero.contains(0));
        System.out.println("Buscamos en el array entero el número 10000 entonces nos devuleve: " + entero.contains(1000));

        System.out.println("\nBuscamos en el array flotante el número 1.3 entonces nos devuleve: " + flotante.contains(1.3));
        System.out.println("Buscamos en el array flotante el número 39.9 entonces nos devuleve: " + flotante.contains(39.9));

        /**
         * y que tal si quisieramos saber la posición en la que se encuentra un
         * elemento en el arreglo, el método indexOf(); y el método
         * lastIndexOf(); nos ayudan con eso, el primero nos devuleve el indice
         * de la primera ocurrencia de la busqueda, y el otro el indice de la
         * ultima ocurrencia, si el elemento no se encuentra en la lista ,
         * simplemente devuelve -1
         */
        System.out.println("\n obteniendo indices de busquedas con los métodos indexOf(); y lastIndexOf();");
        System.out.println("\n buscando el indice de la palabra HOLA 8 en el Array cadena : " + cadena.indexOf("HOLA 8"));
        //agregaremos otro 8 al array entero para que haya dos elementos iguales y porblemos el método lastIndexOf();
        entero.add(8);
        System.out.println("\n buscando la ultima ocurrencia de 8 en el Array entero : " + entero.lastIndexOf(8));
        System.out.println("\n buscando un elemento que no existe en el Array flotante : " + flotante.indexOf(3333.3333));
        /**
         * Por último imaginemos que queremos eliminar un elemento de la lista y
         * que los demas elementos se recorriran para no dejar ese espacio
         * vacío, bueno en este caso debemos usar el metodo remove(); y debemos
         * pasarle como parámetro el elemento a eleminar o la posición del
         * elmento, el método se encargara de eliminarlo y de recorrer los demas
         * elementos, para que no haya espacios vacíos
         */
        System.out.println("\n\n Eliminando elementos de  los ArrayList");

        System.out.println("\nEliminando de el ArrayList cadena por elemento   HOLA 0 ");
        cadena.remove("HOLA 0");
        System.out.println("\nEliminando de el ArrayList entero el elemento en la posicion 4");
        entero.remove(4);
        System.out.println("\nEliminando del ArrayList flotante el elemento 6.3");
        flotante.remove(6.3);

        System.out.println("Imprimiendo los Arrays Modificados: ");

        System.out.println(cadena);
        System.out.println(entero);
        System.out.println(flotante);

    }

}
Esto es todo por esta entrada, más adelante se publicarán entradas de ArrayList más avanzadas en las que pondremos a prueba las funcionalidades de esta maravillosa clase de la API de Java.

sábado, 28 de junio de 2014

Números Grandes en Java

Manejo básico de BigInteger.

En el API de Java,  paquete java.math se encuentra la clase BigInteger.
import java.math.BigInteger;

La clase BigInteger nos permite procesar números con N cantidad de dígitos, donde N es un número considerablemente alto.

*BigInteger solo permite valores del tipo entero.
**Para números decimales con una cantidad grande de dígitos se utiliza BigDecimal.*Se explicara en otra entrada al blog.

Importancia del Biginteger.

La importancia de BigInteger radica en la cantidad de dígitos en un número, teniendo en cuenta que:

Nombre        Rango Aproximado

byte              -128 a 127
short             -32768 a 32767
int                  -2147483648 a 2147483647
long               -9223372036854775808 a 9223372036854775807

Donde la mayor cantidad de dígitos que se puede tener en números enteros es en el uso de un long con la cantidad de 19 dígitos.

Uso del Biginteger.

Para hacer uso de un BigInteger se crea de las siguientes maneras:

·         Forma 1:

Uso de las variables estáticas en BigInteger, la clase tiene 3 variables estáticas que nos facilitan la inicialización del objeto.

Crea el BigInteger con valor de inicio:

1   [ uno ] - BigInteger.ONE
10 [ diez ] - BigInteger.TEN;
0   [ cero ] - BigInteger.ZERO;

BigInteger forma1 = BigInteger.ZERO;

·         Forma 2:

En la creación del objeto BigInteger se manda como parámetro el número como cadena de caracteres o datos de tipo numérico convertido a String, o simplemente leer desde teclado usando Scanner.

Parámetro pasado como cadena:
String numero = “123456789101112”;
BigInteger forma2 = new BigInteger(numero);

Parámetro pasado como long:
long num = 9223372036854775807L;
BigInteger forma2 = new BigInteger(num+"");

Parámetro leído desde teclado usando Scanner:
            Scanner s = new Scanner (System.in);
            BigInteger num = s.nextBigInteger();

Operaciones básicas con BigInter:

Suma – add() –

        Se usa el método .add() para sumar 2  números del tipo BigInteger.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");
       
        BigInteger resultado = uno.add(dos);
        System.out.println("Resultado de suma de 2 objetos BigInteger : "+resultado);

Resta – subtract() –

        Se usa el método .subtract() para restar 2  números del tipo BigInteger.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.subtract(dos);
        System.out.println("Resultado de resta de 2 objetos BigInteger : " + resultado);

Multiplicación – multiply () –

        Se usa el método .multiply () para multiplicar 2  números del tipo BigInteger.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.multiply(dos);
   System.out.println("Resultado de multiplicación de 2 objetos BigInteger : " + resultado);

División – divide () –

        Se usa el método .divide () para dividir 2  números del tipo BigInteger.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.divide(dos);
       System.out.println("Resultado de división de 2 objetos BigInteger : " + resultado);

Residuo Modulo – mod () –

        Se usa el método .mod() para obtener el residuo de 2  números del tipo BigInteger.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("4");

        BigInteger resultado = uno.mod(dos);
       System.out.println("Resultado del residuo de 2 objetos BigInteger : " + resultado);

Operaciones de Bits  .xor() - and() - or() –

        Se usan los métodos .xor() - and() - or()  del objeto BigInteger para operaciones de bits.

        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.xor(dos);
        System.out.println("Resultado del xor de 2 objetos BigInteger : " + resultado);
       
        resultado = uno.or(dos);
        System.out.println("Resultado del or de 2 objetos BigInteger : " + resultado);
       
        resultado = uno.and(dos);
        System.out.println("Resultado del and de 2 objetos BigInteger : " + resultado);

Código Completo:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        crearBigIntegerMetodo1();
        crearBigIntegerMetodo2();
        operacionSuma();
        operacionResta();
        operacionMultiplicacion();
        operacionDivision();
        operacionResiduo();
        operacionesDeBits();
    }

    public static void crearBigIntegerMetodo1() {
        // Formas de instanciar un BigInteger :
        // Forma 1:
        BigInteger num1 = BigInteger.ONE;
        BigInteger num2 = BigInteger.TEN;
        BigInteger num3 = BigInteger.ZERO;

        System.out.println("Valor de num1 : " + num1);
        System.out.println("Valor de num2 : " + num2);
        System.out.println("Valor de num3 : " + num3);
    }

    public static void crearBigIntegerMetodo2() {
        // Formas de instanciar un BigInteger :
        // Forma 2:        
        Scanner s = new Scanner(System.in);

        String numero = "9223372036854775807000000";
        BigInteger porString = new BigInteger(numero);
        System.out.println("BigInteger creado por cadena String : " + porString);

        long Long = 9223372036854775807L;
        BigInteger porLong = new BigInteger(Long + "");
        System.out.println("BigInteger creado por long : " + porLong);

        System.out.println("Ingrese un número BigInteger : ");
        BigInteger leidoPorTeclado = s.nextBigInteger();
        System.out.println("El BigInteger leído por teclado es : " + leidoPorTeclado);
    }

    public static void operacionSuma() {
        // Se usa el método .add() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.add(dos);
        System.out.println("Resultado de suma de 2 objetos BigInteger : " + resultado);
    }

    public static void operacionResta() {
        // Se usa el método .subtract() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.subtract(dos);
        System.out.println("Resultado de resta de 2 objetos BigInteger : " + resultado);

    }

    public static void operacionMultiplicacion() {
        // Se usa el método .multiply() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.multiply(dos);
        System.out.println("Resultado de multiplicación de 2 objetos BigInteger : " + resultado);

    }

    public static void operacionDivision() {
        // Se usa el método .divide() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.divide(dos);
        System.out.println("Resultado de división de 2 objetos BigInteger : " + resultado);
    }

    public static void operacionResiduo() {
        // Se usa el método .divide() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("4");

        BigInteger resultado = uno.mod(dos);
        System.out.println("Resultado del residuo de 2 objetos BigInteger : " + resultado);
    }

    public static void operacionesDeBits() {
        // Se usa el método .xor() - and() - or() del objeto BigInteger.
        BigInteger uno = new BigInteger("9223372036854775807");
        BigInteger dos = new BigInteger("9223372036854775807");

        BigInteger resultado = uno.xor(dos);
        System.out.println("Resultado del xor de 2 objetos BigInteger : " + resultado);
        
        resultado = uno.or(dos);
        System.out.println("Resultado del or de 2 objetos BigInteger : " + resultado);
        
        resultado = uno.and(dos); 
        System.out.println("Resultado del and de 2 objetos BigInteger : " + resultado);
    }
}

Con esto concluye el tema de manejo básico de clase BigInteger, demostrando que es una gran ayuda para realizar operaciones con números con dígitos muy grandes.

Cualquier duda- comentario – sugerencia estoy a sus órdenes. 

miércoles, 25 de junio de 2014

Métodos de la clase Math en Java.

Cuando estamos programando, muchas veces surge la necesidad de recurrir a una función matemática, por suerte existe una clase de java que tiene muchas funciones matemáticas ya implementadas dentro de sus métodos. Estoy hablando de la clase Math, es una clase que tiene métodos estáticos, y una que otra constante que nos servirán para poder trabajar.

¿A qué me estoy refiriendo con métodos estáticos?
En su forma mas simple, es que para usarlos , no necesitamos de crear un objeto de esta clase, simplemente debemos si es que queremos usar un método de la clase Math, llamar a la clase , poner un punto y llamar al método deseado 

Ejemplo
  Math.random();

De esta manera obtenemos el resultado de la función que hayamos llamado.

Bien entonces empecemos por desarmar a la clase Math....

Primero que nada nombraré a dos contantes muy útiles que estan declaradas aquí una es la constante PI, y la otra en numero de euler E.

Los valores de estas dos constantes son los siguientes: 

PI
3.141592653589793
E
2.718281828459045

para poder utilizarlas debemos llamar a la clase Math seguida de un punto y en mayúsculas el nombre de la constante. aquí podemos ver un ejemplo de como llamarlas.

   
   System.out.println("La constante PI es igual a: "+ Math.PI);
   System.out.println("La constante E es igual a: "+ Math.E);

Con este ejemplo  podremos imprimir los valores de estas dos contantes en la pantalla. como se muestra a continuación:

Constantes de la clase Math







Vamos con la parte interesante, los MÉTODOS, existen gran variedad de metodos en esta clase , con distintas finalidades, los iremos nombrando, pero antes debemos tener en cuenta lo siguiente.
               
·     Las funciones trigonométricas (seno, coseno, tangente, etc) miden en radianes, no en grados, de modo que más de una vez deberemos usar "toRadians" y "toDegrees" si nos resulta más cómodo pensar en grados.

Por suerte esos dos métodos "toRadians()" y "toDegrees()" también pertenecen a esta clase y también podemos usarlos de igual manera. Una vez teniendo en claro lo anterior, podemos ir nombrando los métodos que nos interesan para trabajar con funciones matemáticas a través de la clase Math.

Empecemos por las  funciones trigonométricas

 En la clase Math podemos encontrar las siguientes :
       
  • acos()             Arco coseno
  • asin()              Arco seno
  • atan()             Arco tangente entre -PI/2 y PI/2
  • cos(double)   Coseno
  • sin(double)    Seno
  • tan(double)    Tangente

Si quisiéramos imprimir estas funciones con valores aleatorios haríamos lo siguiente:

   
        System.out.println("Arcocoseno de 45º = " + Math.acos(Math.toRadians(45)));
        System.out.println("Arcoseno de 45º = " + Math.asin(Math.toRadians(45)));
        System.out.println("Arcotangente de 45º = " + Math.atan(Math.toRadians(45)));
        System.out.println("Coseno de 45º = " + Math.cos(Math.toRadians(45)));
        System.out.println("Seno de 45º = " + Math.sin(Math.toRadians(45)));
        System.out.println("Tangente de 45º = " + Math.tan(Math.toRadians(45)));          

Es importante poner atención a como se saco por ejemplo el seno de 45 grados,
Observa que usamos primero la función Math.sin(); y como argumento le pasamos el 45 pero convertido a radianes con la función Math.toRadians(45); , esto por que como ya habíamos mencionado, las funciones trigonométricas de esta clase miden los valores en radianes.


La salida  para el código anterior es la siguiente:


Resultados de usar las funciones trigonométricas de la clase Math










Es hora de ver otros métodos interesantes de la clase Math, como lo son, los redondeos:

Estos son una parte importante de analizar, puesto que muchas veces tendremos que ver maneras de redondear de distintas maneras un numero. Para nuestra suerte la clase Math también tiene distintos métodos que permiten redondear de distintas maneras, veamos cuales son :

  • ceil()                       Entero mayor más cercano
  • floor()                      Entero menor más cercano
  • rint(double)            Entero más próximo
  • round()                   Entero más cercano (redondeo de la forma habitual)


si quisiéramos probar estas funciones , imprimiendo las con valores random , seria como sigue 

  
        //Redondeo con el método ceil 
        System.out.println("Redondear 1.9 al valor mayor entero mas cercano " + Math.ceil(1.9));
        System.out.println("Redondear 1.2 al valor mayor entero mas cercano " + Math.ceil(1.2));
        System.out.println("Redondear 1.5 al valor mayor entero mas cercano " + Math.ceil(1.5));
        //Redondeo con el Método floor
        System.out.println("Redondear 1.9 al valor menor entero mas cercano " + Math.floor(1.9));
        System.out.println("Redondear 1.2 al valor menor entero mas cercano " + Math.floor(1.2));
        System.out.println("Redondear 1.5 al valor menor entero mas cercano " + Math.floor(1.5));
        //Aproximación al entero más próximo  con el método rint
        System.out.println("Entero mas proximo de 1.2 = " + Math.rint(1.2));
        System.out.println("Entero mas proximo de 1.5 = " + Math.rint(1.5));
        System.out.println("Entero mas proximo de 1.9 = " + Math.rint(1.9));
        //Redondeo habitual con el metodo round
        System.out.println("Redondero habitual de 1.2 = " + Math.round(1.2));
        System.out.println("Redondero habitual de 1.5 = " + Math.round(1.5));
        System.out.println("Redondero habitual de 1.9 = " + Math.round(1.9));


El resultado de este código seria el siguiente:
Distintos Redondeos con métodos de la clase Math











Aunque estos métodos de redondeo son muy buenos, no son los únicos ,puesto que Java tienes mas clases implementadas para ello, estas las abarcaremos en publicaciones posteriores.

Por ultimo veremos algunos otros métodos interesantes :
  • abs()                       Valor absoluto
  • exp()                       Exponencial
  • log()                        Logaritmo natural (base e)
  • max( , )                   Máximo de dos valores
  • min( , )                    Mínimo de dos valores
  • pow( , )                   Primer número elevado al segundo
  • random()                Número aleatorio (al azar) entre 0.0 y 1.0
  • sqrt()                       Raíz cuadrada
  • toDegrees()           Pasa de radianes a grados (a partir de Java 2)
  • toRadians()            Pasa de grados a radianes (a partir de Java 2)
Ejemplo para poder usarlos :
  
         System.out.println("Valor absoluto de 1 = " + Math.abs(1) + "\n Valor absoluto de -1 = " + Math.abs(-1));
         System.out.println("Exponencial  de un numero " + Math.exp(3));
         System.out.println("Logaritmo natural base e" + Math.log(3));
         System.out.println("Maximo de 6 y 7 " + Math.max(6, 7));
         System.out.println("Minimo de 6 y 7 " + Math.min(6, 7));
         System.out.println("5^2 = " + Math.pow(5, 2));
         System.out.println("Número aleatorio " + Math.random());
         System.out.println("Raiz cuadrada de 25 = " + Math.sqrt(25));
         System.out.println("Raiz cuadrada de 213 =" + Math.sqrt(213));
         System.out.println("45º convertidos a radianes = " + Math.toRadians(45));
         System.out.println("180 radianes covertidos a grados = " + Math.toDegrees(180));

y el resultado que proporcionan :
Algunos métodos útiles de la clase Math











Entonces podemos concluir que la clase Math tienen bastantes buenos métodos que podemos implementar a la hora de querer usar alguna formula matemática, recordemos que si ya existe el método para que reinventar la rueda, sin nada mas que agregar, espero sus comentarios dudas, y hasta las próxima.