Junio 22, 2018, 08:51:56 am

Autor Tema: JAVA desde CERO  (Leído 85478 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #30 en: Abril 19, 2012, 12:50:43 pm »
Genericidad

La genericidad en Java es una tecnica que sirve para parametrizar clases con tipos de datos, de esta forma es de gran utilidad cuando vamos a usar una clase contenedora (que almacena cierta imformacion).

El concepto es similar a los template de C++, pero no igual.

Sirve para la reutilizacion de codigo, por ejemplo si queremos hacer una clase que almacene un String y podamos modificarlo y accederlo seria algo asi.

Código: (java) You are not allowed to view links. Register or Login
public class Cadena {
    private String s;

    public void setString(String s){
        this.s = s;
    }

    public String getString() {
        return s;
    }
}

Algo muy simple, ahora si queremos que en un programa exista esa clase y una para los int por ejmplo serian dos clases verdad??

La otra clase seria:

Código: (java) You are not allowed to view links. Register or Login
public class Entero {
    private int i;

    public void setInteger(int i){
        this.i = i;
    }

    public int getInteger() {
        return i;
    }
}

Y desde el main las podriamos utilizar asi:

Código: (java) You are not allowed to view links. Register or Login
public class Main {
    public static void main(String [] args) {
        Cadena c = new Cadena();
        c.setString("Hola");
        Entero e = new Entero();
        e.setEntero(10);
        System.out.println(c.getString() + " " + e.getEntero());
}

Todo anda muy bien, pero las dos clases que contienen datos son IGUALES solo cambia el tipo de dato y despues es todo lo mismo, si fueran clases con mas funcionalidades tendriamos que tener muchisimas lineas de codigo que seria muy similar.

Entonces en estos casos se usa la genericidad, que sirve para que el tipo de dato se especifique en tiempo de ejecucion y no en tiempo de compilacion, deesta forma seria algo asi nuestro programa resultante:

Código: (java) You are not allowed to view links. Register or Login
public class Contenedor<T> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}

Fijense que se agrego un nombre en la declaracion de la clase, entre llaves angulares: <T>. y luego se reemplazo en cada lugar donde estaba el tipo de dato por ese T, ahi pueden poner cualquier nombre, pero lo tienen que respetar en toda la clase.

Tenemos una limitacion, no podemos usar tipos primitivos, como por ejemplo int, pero podemos usar las clases envoltorio que son practicamente lo mismo, ya que Java convierte de int a Integer sin cast (lo que se llama autoboxing).

Entonces ahora desde el main hacemos asi:

Código: (java) You are not allowed to view links. Register or Login
class Main {
    public static void main(String [] args) {
        Contenedor<String> c = new Contenedor<String>();
        c.setContenido("hola");
        Contenedor<Integer> c1 = new Contenedor<Integer>();
        c1.setContenido(10);
        System.out.println(c.getContenido() + " " + c1.getContenido());
        //fijense que no es problema que almacenemos un Integer porque igual podemos hacer
        int num = c1.getContenido(); //anda, y estamos recibiendo un Integer, pero java lo castea a int
    }
}

Fijense que escribimos una sola clase y desde el main creamos dos instancias de la misma con tipos diferentes.

No es muy complicado el concepto en realidad asi que vamos a avanzar un poco mas.

Podemos tener varios parametros de tipos de datos e incluso dentro de una clase generica tener un objeto generico:

Código: (java) You are not allowed to view links. Register or Login
public class Contenedor2 <T, K> {
    private Contenedor<T> contenedor;
    private K valor;
    //...
}

Y desde el main se llamaria asi:

Código: (java) You are not allowed to view links. Register or Login
Contenedor2<String, Integer> c = new Contenedor2<String, Integer>();

Y obviamente pueden contener cualquier cosa, por ejemplo desde el main podramos hacer algode este tipo:

Código: (java) You are not allowed to view links. Register or Login
Contenedor2<Persona, Contenedor<Integer> > c = new Contenedor2<Persona, Contenedor<Integer> >();

Estariamos guardando un objeto de la clase Persona (hecha por nosotros) y un contenedor de integers, que ese contenedor es otra clase (parametrizada) hecha por nosotros.

Genericidad restringida

Tambien podemos decirle que tipos de datos queremos que se almacenen y cuales no, para eso se usa extends, esto normalmente sirve cuando nosotros definimos tipos, por ejemplo:

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T extends Fc> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}

class Fc {
protected int f;
protected char a;

public Fc(char a, int f) {
this.a = a;
this.f = f;
}
}

class Ifc extends Fc {
private int i;

public Ifc(int i, char a, int f) {
super(a, f);
this.i = i;
}

public int sumar() {
return (i + f);
}
}


class Main {
    public static void main(String [] args) {
        Contenedor<Ifc> c = new Contenedor<Ifc>();
        Contenedor<Fc> c1 = new Contenedor<Fc>();
        c.setContenido(new Ifc(1, 'a', 2));
        int i = c.getContenido().sumar();
System.out.println(i);
    }
}

Ese  codigo se tendria que entender, solamente dejo almacenar un tipo Fc pero almaceno uno Ifc que como es hijo esta bien, fijense que la ventaja de esto es que podemos usar metodos, ya que los tipos estan limitados, por ejemplo, getContenido devuelve T, y yo despues hice: c.getContenido().sumar(); osea que traigo la estrucura esa y llamo a una metodo.

Y podemos limitar aun mas la genericidad con interfaces, asi:

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T extends Fc & Id> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}

interface Id {
int in = 0;
double d = 0.0;
}

class Fc {
protected int f;
protected char a;

public Fc(char a, int f) {
this.a = a;
this.f = f;
}
}

class Ifc extends Fc implements Id{
private int i;

public Ifc(int i, char a, int f) {
super(a, f);
this.i = i;
}

public int sumar() {
return (i + f);
}
}


class Main {
    public static void main(String [] args) {
        Contenedor<Ifc> c = new Contenedor<Ifc>();
        c.setContenido(new Ifc(1, 'a', 2));
        int i = c.getContenido().sumar();
System.out.println(i);
    }
}

Fijanse que ahora no es posible guardar la clase padre porque esta no implementa la interfaz.

Todo esto sirve si queremos agregar comportamiento a los tipos almacenados, por eso esa interfaz no seria muy util pero podemos obligar a implementar algunos metodos que serian de utilidad.

Herencia

Que pasa si heredamos una clase generica?

Podemos mantener la genericidad de la clase padre.

Código: (java) You are not allowed to view links. Register or Login
public class Contenedor2<T> extends Contenedor<T>
Restringir la genericidad.

Código: (java) You are not allowed to view links. Register or Login
public class Contenedor2<T extends TipoDato> extends Contenedor<T>
Especificar un tipo concreto.

Código: (java) You are not allowed to view links. Register or Login
public class NoContenedor extends Contenedor<T>


Ahora se complica para pasar argumentos porque si tenemos algo del estilo:

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T extends Fc> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}


class Main {
    public static void main(String [] args) {
        Contenedor<Ifc> c = new Contenedor<Ifc>();
        algo(c);
    }
   
    public static void algo(Contenedor<Fc> c) {
    //...
    }
   
}

Falla, porque algo() quiere recibir un conteneder de Fc, y recibe un contenedor de la clase hija, y la herencia de tipos, no hace a la herencia de contenedores de tipos, por eso esta fallando. La solucion es Sacar el tipo Fc e indicar que puede venir cualquier cosa derivada de Fc (como ella misma o un hijo de ella) eso se hace usando el signo de pregunta de esta manera:

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T extends Fc> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}


class Main {
    public static void main(String [] args) {
        Contenedor<Ifc> c = new Contenedor<Ifc>();
        algo(c);
    }
   
    public static void algo(Contenedor<? extends Fc> c) {
    //...
    }
   
}

Es muy simple.

Que pasa si no especificamos el tipo?

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}


class Main {
    public static void main(String [] args) {
        Contenedor c = new Contenedor();
        c.setContenido("Hola");
System.out.println(c.getContenido());
    }
}

Ese codigo anda, y anda bien, pero podria no andar si en ves de agregarle un String hubieramos agregado alguna clase propia, ademas puede que el compilador te avise que estas haciendo algo medio mal.

Que es lo que sucede?, recuerdan que Object es la padre de todas las clases, entonces en realidad al no especificar un tipo esa clase transforma a T en un Object, y luego es interpretado como String porque es un tipo muy basico y la clase esta bien programada, pero podria no ser asi, de todas formas queda claro que de esta forma se almacenan Objects.

Habria que usar un cast de esta forma:

Código: (java) You are not allowed to view links. Register or Login
System.out.println((String)c.getContenido());
Si pusieramos algo del estilo:

Código: (java) You are not allowed to view links. Register or Login
class Contenedor<T extends Fc> {
    private T contenido;

    public void setContenido(T contenido) {
        this.contenido = contenido;
    }

    public T getContenido() {
        return contenido;
    }
}


class Main {
    public static void main(String [] args) {
        Contenedor c = new Contenedor();
    }
}

En ves de Objects seran Fc (la clase que habiamos hecho) lo que se guardaran.

Esta es otra manera de hacer genericidad en Java, pero no es recomendable porque el compilador no nos mira los tipos y todo queda en nuestras habilidades. lo mejor es usar la tecnica de arriba.

Saludos.

Pd: Probablemente se encuentre un poco pobre este capitulo, ya que la genericidad es algo bastante grande en Java, quizas mas adelante lo modifique, si queres agregar algo tu aporte es bienvenido.
« Última modificación: Abril 19, 2012, 03:57:09 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #31 en: Abril 19, 2012, 02:23:09 pm »
Funcionamiento de Garbage Collector


Es bien sabido que los programas en java no son ejecutados/interpretados directamente por el sistema operativo como lo son en C por ejemplo, sino que los programas en java para poder llagar a ser multiplataforma corren bajo un sistema operativo reducido adicional.

Este sistema operativo reducido solo tiene la capacidad de ejecutar cualquier programa en java y dado el caso de adaptarse al sistema base. (En realidad puede hacer mas cosas pero para ahora solo sirve saber esto)

Porque se habla tanto de que  java es multiplataforma si otros lenguajes tambien lo son??

En el caso de C el soporte multiplataforma de este lenguaje se debe a que casi todos los sistemas operativos que usamos estan programados en C (y asm) por eso al estar programado en C indefectiblemente esta listo para recibir otras aplicaciones en C. Tampoco quiere decir que sea multiplataforma total.

Que hay de perl, python y demas ??

Esos trabajan con el mismo funcionamiento teorico de java, tiene un software especial que se adapta a cada plataforma y los programas son interpretados por dicho software, pero todos estos lenguajes son interpretados.

Java es compilado, por lo tanto es mas rapido que los interpretados, y no porque se ejecute en la JVM sera ademas mas lento que los demas compilados, de hecho en los Benchmarks hechos a java se ha determinado que java es igual de eficiente que C++, ademas en algunos casos supera en velocidad a C como en el caso de Neville Interpolation o LUP matrix inversion (este ultimo por mucho),

Este sistema operativo reducido que se encarga de que las aplicaciones corran en varias plataformas es la Java Virtual Machine (JVM), como funciona?

Cuando llamamos una clase o un conjunto de ellas el SO base abre un espacio de memoria (en ram) para que se almacene la JVM y para que pueda ejecutar cualquier tipo de programa salvo casos especiales.

Esta JVM se compone de tres espacios de memoria, muy similar al SO base.

Zona de datos
Stack
Heap


La zona de datos es un espacio en memoria dentro de la JVM que una vez que se complete al principio del programa se mantendra fijo hasta el final, todo lo que esta ahi no sera cambiado ni borrado...

Aca entran por ejemplo las constantes o variables de clase en caso de ser una clase, en fin datos estaticos y constantes.

En la famosa pila (stack) se almacenan por ejemplo variables locales, parametros retornos de metodos, etc.

El espacio que ocupara la pila es constante y reconocido en tiempo de compilacion, pero en algunos casos de que no estemos utilizando paramentros ni variables locales estara casi vacio, a pesar de que en el mismo programa en algun otro metodo lo llenemos....

En el caso de llenarlo obtendremos un Stack Overflow , un tipo de Buffer Overflow, y el error en tiempo de ejecucion sera StackOverflowError.

Pero java fue diseñado para ser un lenguaje seguro ... porque es tan facil producir stacks overflows??

Es simple, el stack overflow es producido en el stack de la JVM y no en el Stack que nos interesaria que es el del SO base, por lo tanto podes producir 10000 stacks overflows que el SO base no cambiara los permisos de la JVM y no podremos ejecutar codigo arbritario. (hablando de los stacks overflows que son faciles de producir, tambien tiene sus vulnerabilidades esta maquina virtual).

El espacio que falta es el Heap, o memoria dinamica, este es el unico espacio no conocido en tiempo de compilacion, aca se guardan los objetos y la JVM le asigna un espacio por defecto en caso de nesesitar mas se lo pedira al SO base, tambien es posible obtener errores de heap overflow, pero con muchisima mas cantidad de datos almacenados.

Sin embargo no es recomendable que el heap nesesite mucha memoria, osea, en programas con muchos objetos es nesesario y esta bien, pero al llenarse el heap se lanza la excepcion OutOfMemoryException y esta excepcion no es bien vista por nadie en ningun lenguaje.

Para explicar mejor el stack y el heap se puede decir que en el stack se guardan referencias y primitivos, las referencias van a apuntar a objetos en el heap, y estas tiene un tipo que esta dado por las clases (una referencia del tipo "Hola" solo podra apuntar a objetos del tipo y subtipo "Hola")

Los tipo de referencia no pueden cambiar (recuerden que el tamaño es fijo del stack).

En el heap como dije estan los objetos y es sumamente nesesario que sea un espacio dinamico ya que muchas veces la creacion de objetos esta mas dada por el usuario que por el programa.

Supongan que es un programa reproductor de musica al que cada musica en cola es un objeto, como saber si el usuario solo escuchara una musica o pondra en cola 1000 canciones, entonces a de ser dinamico.

veamos algo mas practico:

Código: (java) You are not allowed to view links. Register or Login
public class Saludo{
            public static void main(String[] args) {
                        Saludo hola = new Saludo();
            }
}

como podemos ver aca lo que pasa dentro es lo siguiente:

En el stack se almacenara "hola" como variable local del metodo main(String[] args) y esta variable local no es mas que una refencia del tipo "Saludo". Despues tenemos un operador new, que crea un nuevo objeto.


Significa que se creara un objeto de tipo "Saludo" (que nombre tiene el objeto, ¿hola?, no! no tiene nombre, tiene direccion en memoria en la JVM y la variable local "hola" que es del mismo tipo hace referencia a la direccion de memoria)

Por lo tanto se dice que:

Código: (java) You are not allowed to view links. Register or Login
Saludo hola = new Saludo();
Tipo referencia = objeto

Asignamos el tipo (asi como en la variable primitivas en int o double o float aca es Saludo) decimos que hara referencia (el ejemplo de las variables primitivas seria lo mismo que "int var")

y por ultimo el contenido en si (el ejemplo de la variable primitivas seria un numero)

espero que haya quedado claro


Código: You are not allowed to view links. Register or Login
Stack          Heap
.......       ........
.......       ........
hola------->new Saludo
.....         .........

Ahora bien, supongamos que queremos llenar el heap para hacer muchas excepciones del tipo OutOfMemoryException que aparentemente no es algo muy recomendado =D

Vamos a hacerlo!!


Código: (java) You are not allowed to view links. Register or Login
public class Saludo {
            public static void main(String[] args) {
                        Saludo hola;
                        hola = new Saludo();
                        hola = new saludo();
                        hola = new Saludo();
                        hola = new Saludo();
                        hola = new Saludo();
                        hola = new Saludo();
                        hola = new Saludo();
            }
}

Recuerden que cada ves que pongamos new se crea un nuevo objeto.....

Bien logramos la excepcion que queriamos?? no =P

Que paso?? si cada new hace nuevos objetos se tendria que haber llenado....si, quizas se tubiera que haber llenado(supongan que habia muchisimos mas new), pero la referencia fue siempre la misma (hola).

y? los objetos se crearon....

Código: You are not allowed to view links. Register or Login
Stack          Heap
.......       new Saludo
.......       new Saludo
hola------->new Saludo
.....         new Saludo

Ahora si llegamos a lo que se queria explicar.

Un objeto sin referencia es un objeto que no se utilizara mas, porque el valor de memoria se "solto" y es imposible encontrar donde esta ese objeto en una memoria dinamica, por lo tanto al "soltarse" (no referenciarlo) se supone que no se usara mas.

He aqui donde la Garbage Collection hace su labor y pasa por el heap limpiando la "basura" (objetos no referenciados desde el stack).

Lo comodo de java es que la Garbage Collection hace el labor automaticamnete, en C por ejemplo habia que eliminarlo directamente desde el codigo y podia llegar a haber problemas si sacabamos mal las cuentas.

Cabe destacar que java no deja atras la opcion manual sin embargo cuando lo hagamos es casi seguro que la Garbage Collection ya ha pasado, o en otro caso no ha podido pasar por algun problema en especial, cosa que si la llamamos tampoco podra hacerlo...

Para los curioso asi la pueden invocar:

Código: (java) You are not allowed to view links. Register or Login
System.gc();
la Garbage Collection lo que hace es pasar por el stack y almacena todas las referencia, luego se va al heap y no borra el objeto que tenga referencia, asi que quien no este referenciado y ocupando lugar en el heap inutilmente se va =D

Código: (java) You are not allowed to view links. Register or Login
public class Saludo {
    public static void main(String[] args) {
        Saludo hola = new Saludo();
        Saludo chau= new Saludo();
        hola = chau;
    }
}

que sugiere este programa.....

hacemos una variable local llamada "hola" que apunta a un objeto
hacemos una variable local llamada "chau" que apunta a otro objeto
la variable local llamada "hola" dejara de apuntar al objeto que apuntaba antes y apuntara al mismo objeto que apunta la variable "chau"

Por lo tanto el primer objeto que fue creado no tiene referencia osea que cuando pase la "recolectora de basura" se lo llevara =D

ahora bien que pasa si agregamos una linea asi

Código: (java) You are not allowed to view links. Register or Login
public class Saludo {
    public static void main(String[] args) {
        Saludo hola = new Saludo();
        Saludo chau= new Saludo();
        hola = chau;
        chau = null;
    }
}

que hara de distinto la Garbage Collection  con respecto al otro programa??

es obvio que nada ya que el objeto estaba apuntado por dos variables locales desde el stack y ahora solo quedo apuntado por una, lo suficiente para que se quede donde esta.

Por ultimo hablarles de algo no muy conocido.

se llama Island of Isolation y se da cuando atributos de un objeto apuntan a otro pero estos igual son borrados.

Código: (java) You are not allowed to view links. Register or Login
public class Saludo {
    public Saludo atributo;
    public static void main(String[] args) {
        Saludo hola = new Saludo();
        Saludo chau = new Saludo();
        hola.atributo = chau;
        chau.atributo = hola;
        hola = null;
        chau = null;
    }
}

como pueden ver se borran (null) las referencias que habia para dichos objetos pero, un atributo del objeto 1 hace referencia al objeto 2 y un atributo del objeto 2 hace referencia al objeto 1. (Si miran el codigo con detemiento lo entederan)

En este caso los dos objetos vas a ser borrados por la Garbage Collection.

Porque sucede esto, bien porque en si por mas que esten entrelazados estos objetos los dos son nulos por lo que una cosa que jamas se va a usar apunta a una cosa que jamas se va a usar y la otra cosas que jamas se va a usar apunta a la que la esta apuntando que jamas se va a usar (quizas los enrede pero es que un objeto perdido apunta a otro perdido y viceversa)

por lo tanto se eliminan....

aunque en el caso este por ejemplo

Código: (java) You are not allowed to view links. Register or Login
public class Saludo {
    public Saludo atributo;
    public static void main(String[] args) {
        Saludo hola = new Saludo();
        Saludo chau = new Saludo();
        hola.atributo = chau;
        chau.atributo = hola;
        hola = null;
    }
}


Ningun objeto sera eliminado ya que hay uno que no tiene referencia propiamente dicha pero un objeto que si sirve tiene un atributo apuntando a el asi que los dos se quedan

¿El Garbage Collection hace mas lento mi programa?

Esas son teorias que surgen generalmente por programadores que estan en contra de java, el hecho es que si, si es mas lento, pero de todas formas es nesesario tenerlo, porque si un lenguaje no la tiene un programa ocuparia muchisimo lugar en vano en la memoria al hecho de que cualquier aplicacion podria saturarla, y los lenguajes que tienen pero hay que llamarla siempre, generalmente tambien ocupan mucho lugar en memoria innesesario e incluso aveces puede llegar a haber problemas.

Puden visitar You are not allowed to view links. Register or Login para informacion mas detallada de la GC.

Saludos
« Última modificación: Abril 21, 2012, 10:21:04 am por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #32 en: Abril 19, 2012, 05:14:17 pm »
Clase Object

Como ya les venia deciendo todos los objetos, a la larga, son hijos de la clase Object.

Esta clase tiene algunos metodos que son de utilizada y que a veces es nesesario utilizarlos, vamos a ver:

Código: (java) You are not allowed to view links. Register or Login
public class Object {
    public final Class getClass() { . . . }
    public String toString() { . . . }
    public boolean equals(Object obj) { . . . }
    public int hashCode() { . . . }
    protected Object clone() throws CloneNotSupportedException { . . . }
    protected void finalize() throws Throwable { . . . }     
   
    public final void wait() throws IllegalMonitorStateException,
                                      InterruptedException { . . . }
    public final void wait(long millis) throws IllegalMonitorStateException,
                                                  InterruptedException {. . .}
    public final void wait(long millis, int nanos) throws
                                             IllegalMonitorStateException,
                                             InterruptedException { . . . }
    public final void notify() throws IllegalMonitorStateException { . . . }
    public final void notifyAll() throws   
                                    IllegalMonitorStateException { . . . }
}

Todos los wait, notify y esos no los vamos a ver ahora porque son para cuando se programa con hilos. Asi que quedan:

Código: (java) You are not allowed to view links. Register or Login
getClass() //devuelve el objeto del tipo Class que representa dicha clase durante la ejecución
toString() //devuelve una cadena describiendo el objeto
hashCode() //devuelve (con alta probabilidad) un valor distinto para cada objeto
finalize() throws Throwable //se usa para finalizar el objeto
De este ya algo sabemos:
Código: (java) You are not allowed to view links. Register or Login
equals(Object obj) //compara si dos objetos son iguales, por defecto un objeto es igual solamente a si mismo

Y este ya lo vimos, as que no va a entrar:
Código: (java) You are not allowed to view links. Register or Login
clone() throws CloneNotSupportedException
Primero vamos a explicar equals que ya de algun lado lo tenemos, asi es, para comparar los Strings.

equals


Con el operador == cuando lo usamos con objetos estamos comparando a nivel de memoria si el objeto es el mismo, ahora si tenemos una clase que almacena un dato especifico, y para nosotros dos objetos de esa clase son iguales si el dato es igual, tenemos que indicar como es que se comparan esas clases (en C++ se puede sobregargar el operador == aca se sobrecarga el metodo equals())

Veamos un ejemplo:

Código: (java) You are not allowed to view links. Register or Login
class MiClase {
   
    int dato;
   
    MiClase( int dato ) {
        this.dato = dato;
    }
 
    public boolean equals( Object obj ) {

        if((obj != null) && (obj instanceof MiClase)) {
           
            MiClase cas = (MiClase)obj;

            return( this.dato == cas.dato );
        } else {
            return false;
        }
    }
}

class Main {
       
    public static void main(String args[] ) {
        MiClase o1 = new MiClase( 2 );
        MiClase o2 = new MiClase( 2 );
        MiClase o3 = new MiClase( 3 );
        String  o4 = "Un objeto String";

        System.out.println("o1 == o1: " + o1.equals(o1));
        System.out.println("o1 == o2: " + o1.equals(o2));
        System.out.println("o1 == o3: " + o1.equals(o3));
        System.out.println("o1 == o4: " + o1.equals(o4));
    }

}

Como pueden ver aca se crea una clase que contiene un numero, y a nosotros nos interesa saber si el numero es igual o no, no nos importan los demas metodos (que por cierto no hice ninguna xD) entonces sobreescribimos el metodo equals(Object).

Es importante que se sobreescriba asi que tienen que respetar los argumentos, si no lo hacen seria una sobrecarga, tambien tiene que ser public y boolean.

Una ves dentro primero preguntamos si el objeto que esta como parametro realmente existe:

Código: (java) You are not allowed to view links. Register or Login
(obj != null)
Y luego se usa el operador instanceOf, que es un operador medio mal visto desde el punto de programacion rientada a objetos pero pasa este caso es nesesario, porque tenemos que preguntar si los dos objetos son instancias de la misma clase, eso es lo que hace instanceOf devuelve true si ambos objetos son intancias de la misma clase, ok?

En caso afirmativo tenemos que castear el Object a la clase que se esta comparando:

Código: (java) You are not allowed to view links. Register or Login
MiClase cas = (MiClase)obj;
Y luego hacemos todas las comparaciones que queramos, en este caso solo se compara el nuemro asi que con.

Código: (java) You are not allowed to view links. Register or Login
return( this.dato == cas.dato );
Alcanza, eso seria lo mismo que:

Código: (java) You are not allowed to view links. Register or Login
if(this.dato == cas.dato) {
    return true;
} else {
    return false;
}

Y ademas si el objeto era null o no era instancia de la misma clase se devuelve false (que es lo que pasa con el casao de String).

Ya saben como comparar y clonar sus objetos, vamos por mas.

toString

toString es utilizado para pedirle al objeto algun String que nos pueda llegar a ser de utilidad.

Por ejemplo si llamamos a toString de la clase Integer, esta nos devuelve el numero que tiene como un String =D

Código: (java) You are not allowed to view links. Register or Login
class Main {
    public static void main(String args[] ) {
    Integer i = new Integer(10);
        String s = i.toString();
    }
}

Ya se encontraran con mas clases de la API que tienen un toString() bastante interesante.

Por ahora lo nuestro es apreder a hacerlos, y de verdad que es muy simple, tenemos una clase y queremos pedirle un String que represente la informacion de esa clase, simplemente sobrecargamos y retornamos.

Si no definimos nada, y llamamos a este metodo sera el metodo de Object, el que no esta sobreescrito, y este devolvera algo que puede que nos sea de utilidad como que no. por ejemplo prueben:

Código: (java) You are not allowed to view links. Register or Login
class PointCoordinates {

private int x, y;
public PointCoordinates(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}

class ToStringDemo {

public static void main(String args[]) {
PointCoordinates point = new PointCoordinates(10, 10);

System.out.println("Object toString() method : " + point);

String s = point + "(se llamo al metodo implicitamente)";
System.out.println(s);
}
}
*ejemplo sacado de You are not allowed to view links. Register or Login.

Y se pueden hacer metodos toString() personalizados.

Código: (java) You are not allowed to view links. Register or Login
class PointCoordinates {

private int x, y;
public PointCoordinates(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// Custom toString() Method.
public String toString() {
return "X=" + x + " " + "Y=" + y;
}
}

class ToStringDemo {

public static void main(String args[]) {
PointCoordinates point = new PointCoordinates(10, 10);
System.out.println(point);
String s = point + " (se llama implicitamente)";
System.out.println(s);
}
}

Fijense que lo unico copado que tiene que que no hace falta llamar al metodo, porque sino se resuelve con cualquier metodo orinario, para aca estamos mostrando por pantalla el objeto, eso es lo que hace toString().

hashCode

hashCode por ahi traiga un poco de dificultad a la hora de entenderlo, pero no importa demaciado porque se usa para casos algo particulares que quizas mas delante veamos (basicamente sirve para el maneja de HashMap y HashSet).

Basicamente hashCode devuelve un unico numero para cada objeto, de esta forma esta relacionado en parte con el metodo equals, si segun equals los objetos son iguales, entonces tienen que tener el mismo hashCode.

No se si tiene mucho sentido explicarlo porque es algo batante inusual y ahora no sirve de mucho, sin embargo pueden ver estos links:

You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login

finalize

Ya vimos como funciona la Garbage Collector en el capitulo anterior, ahora vamos a ver este metodo que nos puede llegar a interesar.

Antes de que el objeto sea eliminado por la GC se llama al metodo finalize() del mismo, esto hace que podamos efectuar una ultima accion antes de que sea borrado, usualmente podemos mostrar algo por pantalla, como un aviso de que ese objeto dejo de existir, podemos aprovechar a guardar ciertos datos o sino para lo que mas se usa es para liberar recursos que ese objeto este usando (todavia no sabemos nada de esto, lo veremos con usemos archivos, streams y redes).

Es algo simple, si queremos alterar el comportamiento de finalize() de la clase Object lo sobreescribimos y listo:

Código: (java) You are not allowed to view links. Register or Login
protected void finalize () throws throwable {
    // Lo que queremos hacer cuando el objeto de esta clase se valla a eliminar.
}

Como posiblemente los padres de este objeto tambien tengan recursos, por guardar o soltar, o lo que sea, y sus metodos finalize() ya esten hechos, no esta mal hacer:

Código: (java) You are not allowed to view links. Register or Login
protected void finalize() throws Throwable {
    // Lo que queremos hacer cuando el objeto de esta clase se valla a eliminar.
    super.finalize();
}

No es sumamente nesesario usarlo pero nos pede servir de utilidad este metodo que es el ultimo que se ejecuta (seria una especie de destructor en C++ pero no es de la mismas caracteristicas, ya que en realidad no cumple esa funcionalidad).

getClass

El metodo getClass() es final, asi que aca no se puede sobreescribir nada, lo que hace este metodo es devilver un objeto "Class" que representa a nuestro objeto actual.

Que es Class? es una clase de la API de java: You are not allowed to view links. Register or Login.

Lo que importa en realidad es lo que se puede hacer con este objeto.

Podemos tener un monton de informacion acerca de la clase a la que le hicimos el getClass, por ejemplo: podemos saber su nombre, el de su padre, si implementa interfaces, si es clase o interfaz, el nombre de su package, saber sus metodos y variables, crear una nueva instancia de la misma y algunas cosas mas (Ya lo deben haber visto en la documentacion)

Cuando es nesesario esto? Basicamente cuando tenemos un objeto pero no sabemos nada acerca de el, entonces al no tener el nombre de la clase de la cual esta instanciado ese objeto se nos hace imposible crear una nueva instancia.

Con esto es posible, por ejemplo podemos hacer:

Código: (java) You are not allowed to view links. Register or Login
void printClassName(Object obj) {
         System.out.println("La clase de " + obj +
                            " es " + obj.getClass().getName());
}

Con eso sabemos el nombre de la clase del cual proviene obj.

Tambien podemos crear una instancia de esta forma:

Código: (java) You are not allowed to view links. Register or Login
Object createNewInstanceOf(Object obj) {
    return obj.getClass().newInstance();
}

Bueno y muchas cosas mas, ya esta comentado los metodos mas importantes de esta clase que como se habran dado cuanta son todos medios especiales.

Aca esta la You are not allowed to view links. Register or Login de la clase Object, para que la tengan a mano.

Saludos
« Última modificación: Abril 20, 2012, 02:33:30 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #33 en: Abril 20, 2012, 02:32:56 pm »
Colecciones en Java

Algo muy importante en un lenguaje de programacion son las estructuras de datos, hasta ahora nosostros hemos visto los arreglos y ademas vimos las clases como beans, que nos permiten crear cualquier contenedor o estructura, estas dos formas de almacenar datos tienen un problema cada una. Los arreglos como se daran cuenta a esta altura del curso no cuantan con las ventajas de la programacion orientada a objetos, y las clases que nosotros creemos para usar como estructura de datos ... estan programadas por nosotros xD

Dentro del paquete java.util de la API de Java hay una serie de clases e interfaces que forman un conjunto de estructuras de datos para poder usar de forma facil, rapida y con las ventajas de la OOP.

Todas estas estructuras hacen uso de la genericidad, asi que es importante saberla.

Basicamente dentro de java.util hay una interface llamada Collection<E> que es la principal interface de todas las estructuras de datos de un solo valor (You are not allowed to view links. Register or Login).

Y la interface Map<K, V> que es la principal de todas las estructuras con un par de valores (You are not allowed to view links. Register or Login).

Tiene un monton de estructuras de datos, muchisimas, aca vamos a ver las que mas se suelen usar y las demas si las llegan a necesitar ya se las arreglaran.

Aca les dejo una imagen que muestra mas o menos las estructuras mas usadas para que se den una idea:


Si no sabes mucho sobre estructuras de datos seria mejor que antes leyeras algo al respecto, es muy recomendable saber de este tema para poder programar bien y elegir la mejor opcion para almacenar nuestros datos.

Podes leer que es una You are not allowed to view links. Register or Login, y algunas estructuras de datos de las mas usadas como por ejemplo:

You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login.

Hay muchas mas por aprender si queren saber todas.

Ya tendran mas o menos una idea que es cada estructura vamos a empezar.

Lo primero es separar a la interface Collection<E> en tres de sus interfaces hijas que son las que mas se usan:

List<E>
Set<E>
Queue<E>


Que como ya se imaginaran definen el comportamiento abstracto de listas, conjuntos y filas.

Vamos a por las List, definen estructuras secuenciales con posibilidad de duplicacion de datos, donde cada dato tiene una posicion. Bajo esta interfaz nos vamos a encontrar con estructuras como los arreglos, listas y pilas. Veremos que tiene estructuras como:

Stack<E>
Vector<E>
ArrayList<E>
LinkedList<E>
ArrayDeque<E>


Set<E> tiene tres estructuras importantes:

HashSet<E>
LinkedHashSet<E>
TreeSet<E>


Y tambien veremos Queue<E>, una fila normal y una PriorityQueue<E>


Dentro de lo que es Map<K, V>, veremos:

HashMap<K, V>
HashTable<K, V>
LinkedHashMap<K, V>
TreeMap<K,V>
WeakHashMap<K, V>
IdentityHashMap<K, V>.


No se asusten, solo las veremos como se usan y la mayoria no las usaran nunca xD

Ademas veremos 2 interfaces que son Comparable y Comparator usadas para fomentar un orden en la estructura

Y tambien veremos la interface Iterator<T>

Por ultimo veremos que cosas interesanres hay en la clase Collections.

Repito devuelta, estas no son todas las estructuras que existen ahi, hay muchas mas, algunas mas generales, otras mas especificas, de todos los colores y tamaños.

Vamos a empezar
« Última modificación: Abril 21, 2012, 10:37:48 am por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #34 en: Abril 21, 2012, 08:44:23 am »
ArrayList

You are not allowed to view links. Register or Login

La primer estructura que vamos a ver es el ArrayList, es practicamente el equivalente a los arreglos que veniamos viendo pero la principal diferencia es que ArrayList es una clase.

Tiene otra diferencia notable, y es que no es limitado como si lo era un arreglo. En un arreglo una ves que asignabamos un espacio (por ejemplo 10 elementos) si queriamos meter 11 elementos era imposible porque el arreglo nos quedaba chico. El ArrayList no tiene esta limitacion, tiene la capacidad de crecar si es que se quieren agregar mas elementos al ArrayList.

Sin embargo no hay que abusar de esta caracteristica porque crece siguiendo la formula :  (capacidad * 3) / 2 + 1

Osea que si queremos agregar un elemento mas al arreglo que esta lleno, este crece 3/2 de su tamaño actual y podriamos estar gastando mucha memoria en vano.

Por defecto un arraylist se crea con capacidad inicial para 10 elementos:

Código: (java) You are not allowed to view links. Register or Login
ArrayList<String> lista = new ArrayList<String>();
Pero se puede especificar un tamaño personalizado llamando a un constructor sobrecargado asi:

Código: (java) You are not allowed to view links. Register or Login
ArrayList<String> a = new ArrayList<String>(50);
Si bien estas definiciones son correctas lo ideal es hacer uso del polimorfismo para que si una ves en nuestro programa decidimos cambiar el ArrayList por otra estructura podamos facilmente adaptarlo, por eso la forma de definirlo quedaria asi:

Código: (java) You are not allowed to view links. Register or Login
List<String> lista = new ArrayList<String>();
Donde List es la interface que ya hemos hablado que tiene varios hijos mas, si solo usaremos el arraylist como pueden ver no cambia en nada, asi que no esta mal hacer esto.

El ultimo constructor de ArrayList permite que se le entrege una Collection y la copia a el arratlist, de esta forma podes hacer copias e inicializar rapidamente un arraylist.

Ahora vamos a ver algunos de los metodo mas interesantes que tiene esta clase.

Código: (java) You are not allowed to view links. Register or Login
boolean add(E o)Añade un nuevo elemento al final del arraylist.
   
Código: (java) You are not allowed to view links. Register or Login
boolean add(int index, E element)Añade un nuevo elemento en la posicion especificada.
   
boolean addAll(Collection<? extends E> c)
Añade todos los elementos de la coleccion especificada al arraylist.

Código: (java) You are not allowed to view links. Register or Login
void clear()Elimina todos los elementos del arraylist.

Código: (java) You are not allowed to view links. Register or Login
boolean contains(Object o)Comprueba si el elemento especificado es parte del arraylist.

Código: (java) You are not allowed to view links. Register or Login
E get(int index)Recupera el elemento que se encuentra en la posición espeficicada.

Código: (java) You are not allowed to view links. Register or Login
int indexOf(Object o)Devuelve la primera posicion en la que se encuentra el elemento especificado en el arraylist, o -1 si no se encuentra.

Código: (java) You are not allowed to view links. Register or Login
int lastIndexOf(Object o)Devuelve la ultima posicion en la que se encuentra el elemento especificado en el arraylist, o -1 si no se encuentra.

Código: (java) You are not allowed to view links. Register or Login
E remove(int index)Elimina el elemento de la posicion indicada.

Código: (java) You are not allowed to view links. Register or Login
boolean remove(Object o)Elimina la primera ocurrencia del elemento indicado. Si se encuentra y elimina, devuelve true sino false.

Código: (java) You are not allowed to view links. Register or Login
E set(int index, E element)Reemplaza el elemento que se encuentra en la posicion indicada por el elemento pasado como parametro. Devuelve el elemento que estaba es esa posicion.

Código: (java) You are not allowed to view links. Register or Login
int size()Devuelve el numero de elementos que hay en el arraylist.


Si queremos recorrer un arraylist o mostrar sus elemetos tenemos varias posibilidades:

Para mostrarlo es muy simple, podemos usar el metodo toString de la clase (para que se muestre de forma correcta los elementos que contienen tambien deben tener una forma de mostrarse).

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
List<String> l = new ArrayList<String>();
l.add("Hola");
l.add("Como");
l.add("Estas?");
System.out.println(l);
}
}

Resultado:

Código: You are not allowed to view links. Register or Login
[Hola, Como, Estas?]
Y tambien podemos imaginarnos como hacer con un for y usando get + size

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
List<String> l = new ArrayList<String>();
l.add("Hola");
l.add("Como");
l.add("Estas?");
for(int i=0; i < l.size(); i++) {
System.out.println(l.get(i));
}
}
}

Resultado:

Código: You are not allowed to view links. Register or Login
Hola
Como
Estas?

Como ya sabran con get obtenemos el elemento, y poder hacer cualquier cosa con el, pero tambien es muy util set, para poder hacer reemplazos:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
List<String> l = new ArrayList<String>();
l.add("Hola");
l.add("Como");
l.add("Estas?");

String eliminado = l.set(1, "...");
System.out.println(l);
System.out.println("Elimine: " + eliminado);
}
}

Resultado:

Código: You are not allowed to view links. Register or Login
[Hola, ..., Estas?]
Elimine: Como

Hay otra forma moverse por un arraylist (que por ahora veremos) que es con el foreach:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
List<String> l = new ArrayList<String>();
l.add("Hola");
l.add("Como");
l.add("Estas?");

for(String i : l) {
System.out.println(i);
}

}
}

Resultado:

Código: You are not allowed to view links. Register or Login
Hola
Como
Estas?

Mucho mas lindo no? cualquier coleccion que implemente la interface Iterable<E> puede ser recorida de esta forma.

Vector

You are not allowed to view links. Register or Login

A Vector no le vamos a dar mucha importancia, es basicamente un ArrayList, la principal diferencia es que Vector es sincronizado, eso quiere decir que se usa para entornos multi-hilo y como todavia ni sabemos que es eso lo vamos a dejar de lado.

Vamos a nombrar algunas cosas por si las nesesitan algun dia.

Vector cada ves que se queda sin espacio crece al doble, sin embargo cuanta con un constructor mas que ArrayList que es para especificar como queremos que cresca cuando esto ocurre (ya lo habran visto en la documentacion).

Hay algunas cosas mas relacionadas con el manejo de capacidad, pero como les dije, no le damos importancia.

Aca pueden ver mas detallada la diferencia entre Vector y ArrayList: You are not allowed to view links. Register or Login

Stack

You are not allowed to view links. Register or Login

Stack es una estructura de pila, eso quiere decir que solo podemos obtener de a un elemento y este es el ultimo que entro.

Esta clase es muy sencilla, solo tenemos un constructor vacio para crear la pila, tenemos un metodo para meter, uno para sacar, uno para ver que hay en el tope, uno para saber si esta vacio, y uno que hace una busqueda en toda la pila de un elemento.

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
Stack<String> pila = new Stack<String>();

for (int i=0; i<10; i++) {
pila.push(Integer.toString(i));
}

while (!pila.empty()) {
System.out.println(pila.pop());
}

}
}

Resultado:

Código: You are not allowed to view links. Register or Login
9
8
7
6
5
4
3
2
1
0

Aunque si queremos mostrar nos conviene usar toString de esa clase:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {
public static void main(String... a) {
Stack<String> pila = new Stack<String>();

for (int i=0; i<10; i++) {
pila.push(Integer.toString(i));
}
System.out.println(pila);
}
}

Código: You are not allowed to view links. Register or Login
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Ya sabran como usarla no es muy dificil.

Esta clase hereda de Vector (que era similar a ArrayList) asi que hay muchos mas metodos para usar, pero por ahi se escapa un poco del concepto de pila, si tiene que usar muchos metodos del padre, probablemente eligieron mal la estructura.

LinkedList

You are not allowed to view links. Register or Login

LinkedList representa un lista doblemente vinculada, a grandes rasgos se comporta igual que un arraylist, pero la diferencia es en la implementacion, lo que causa que sependiendo de nuestro problema tengamos que usar una u otra.

Los arraylist tiene acceso aleatorio, por lo tanto son rapidos para hacer busquedas, mientras que linkedlist no permite posicionarse de una en un elemento que queramos, por eso no comviene para hacer busquedas.

Sin embargo en los arraylist ya sabemos lo problemas que hay cuando se llenan para hacerllo crecer, y por ejemplo si queremos agregar elementos al principio es muy costoso porque hay que mover todos los elementos, en LinkedList las incersiones no cuestan nada por como esta implementada, tambien es poco costoso eliminar un elemento (una ves encontrado)

Otro tema es el espacio en memoria, como ya saben un arraylist crece sin medir cuantos elementos van a venir, en cambio una linkedlist lo hace elemento por elemento esto hace que el arraylist ocupe mas memoria:


Y mas o menos estan son las complejidades de cada uno:

Algoritmo                  ArrayList   LinkedList
Acceder al primero      O(1)          O(1)
Acceder al ultimo         O(1)         O(1)
Acceder al medio         O(1)         O(N)
Insertar al principio     O(N)         O(1)
Insertar a lo ultimo      O(1)         O(1)
Insertar en el medio   O(N)          O(1)

Bueno dejando de lado un poco el tema de cuando elegrla y porque vamos a ver como se usa.

Código: (java) You are not allowed to view links. Register or Login
add(E e)
Código: (java) You are not allowed to view links. Register or Login
addLast(E e)Insertan al final de la lista.

Código: (java) You are not allowed to view links. Register or Login
addFirst(E e)Inserta al principio de la lista

Código: (java) You are not allowed to view links. Register or Login
add(int index, E e)Inserta en la posicion que indica index, de la lista

Código: (java) You are not allowed to view links. Register or Login
get(int index)Retorna el elemento que se encuentra en la posicion indicada por index, de la lista

Código: (java) You are not allowed to view links. Register or Login
getFirst()Retorna el primer elemento de la lista

Código: (java) You are not allowed to view links. Register or Login
getLast()Retorna el ultimo elemento de la lista

Y tenemos varios mas para hacer muchas cosas, los pueden mirar de la documentacion oficial.

Se puede mostrar la lista con toString() igual que se hacia con ArrayList, tengan en cuanta que en cuanto a interfaz son casi iguales lo que varia es sobre la estructura que se esta trabajando), por ejemplo tambien podemos hacer el recorido con el for y  get(int index) pero tengan en cuanta que aca, cada get tiene que recorrer el numero de elemento que pasan por parametro, en arraylist era acceso aleatorio (que la interfaz no los engañe, si bien get() parece que nos da acceso aleatorio el costo esta igual).

El foreach sige funcionando con esta estructura:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class asd {

public static void main(String... a) {
List<String> l = new LinkedList<String>();
l.add("Hola");
l.add("Como");

for(String s : l) {
System.out.println(s);
}
}
}

En este caso se recorre la lista una ves mostrandose, no es equivalente a lo que sucedia en ArrayList que los dos lo recorrian de una. Por ahora les parecera algo raro que con foreach se pueda hacer algo asi, pero mas adelante explicare iteradores que es como se consigue esta solucion.
« Última modificación: Abril 27, 2012, 03:01:59 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #35 en: Abril 22, 2012, 03:29:24 pm »
HashSet

You are not allowed to view links. Register or Login

HashSet es el principal conjunto que se usa en Java, un conjunto es un contenedor en donde sus elementos no tienen orden y no tienen duplicados.

Permite buscar un objeto dentro del conjunto de forma rapida ya que internamente es un arreglo y guarda los objetos utilizando un indice calculado con el hashCode del objeto guardado.

Como cada objeto que se va a almacenar no debe estar duplicado y esta comprobacion es mediante hashes si vamos a almacenar nuestros pripios objetos lo ideal es sobreescribir los metodos equals() y hashCode() de la clase Object.

Por ejemplo, si vamos a almacenar una clase de la forma:

Código: (java) You are not allowed to view links. Register or Login
class asd {
private String cadena;
private int numero;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}
//...
}

Vamos a suponer que dos instancias de esa clase son iguales si tienen el mismo String y el mismo numero.

Pero vemos que si dejamos el metodo hashCode() como esta los hashes dan diferentes:

Código: (java) You are not allowed to view links. Register or Login
class asd {
private String cadena;
private int numero;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}
//...
}

class hola {
public static void main(String... a) {
asd l = new asd("Hola" , 3);
asd l1 = new asd("Hola" , 3);
System.out.println(l.hashCode());
System.out.println(l1.hashCode());
}
}

Por eso sobreescribimos el metodo hashCode() para que los hashes sean iguales, para esto a la hora de crear el hash debemos de involucrar a todos los atributos que la diferencian de otra instancia, en este caso son el int y String. String ya es una clase y tiene un metodo hashCode() asi que podemos usarlo para generar el nuevo hash, y int no tiene ese metodo porque no es una clase pero ya de por si es un numero asi que lo usaremos asi como esta.

Vamos a usar el metodo que vimos mas arriba en la parte de la clase Object:

Código: (java) You are not allowed to view links. Register or Login
class asd {
private String cadena;
private int numero;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}

public int hashCode() {
  return getHash( cadena.hashCode(), numero);
}

public static int getHash(int... fieldHashes) {
int result = 17;
for (int hash : fieldHashes) {
result = 37 * result + hash;
}
return result;
}


//...
}

class hola {
public static void main(String... a) {
asd l = new asd("Hola" , 3);
asd l1 = new asd("Hola" , 3);
System.out.println(l.hashCode());
System.out.println(l1.hashCode());
}
}

getHash es static porque genera hashes genericos para cualquier cantidad de elementos que se le pasen, por eso no es siquiera nesesario que este dentro de esa clase, lo pueden agregar a su libreria dentro de algun package y lo usan desde cualquier clase que quieran generar hashCodes.

Como no sabemos cuan costoso es generar dicho hash aca hacemos una pequeña mejora al codigo que seria el final:

Código: (java) You are not allowed to view links. Register or Login
class asd {
private String cadena;
private int numero;
private int hashCode = 0;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}

public int hashCode() {
if(hashCode == 0) {
hashCode = getHash( cadena.hashCode(), numero);
}
  return hashCode;
}

public static int getHash(int... fieldHashes) {
int result = 17;
for (int hash : fieldHashes) {
result = 37 * result + hash;
}
return result;
}


//...
}

class hola {
public static void main(String... a) {
asd l = new asd("Hola" , 3);
asd l1 = new asd("Hola" , 3);
System.out.println(l.hashCode());
System.out.println(l1.hashCode());
}
}

Recordemos que esto es nesesario porque hashSet guarda indices a partir de los codigos hash de cada objeto, pero ademas seria conveniente sobreescribir el metodo equals para que se puedan hacer la comprobaciones de si son o no iguales.

Código: (java) You are not allowed to view links. Register or Login
class asd {
private String cadena;
private int numero;
private int hashCode = 0;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}

public int hashCode() {
if(hashCode == 0) {
hashCode = getHash( cadena.hashCode(), numero);
}
  return hashCode;
}

public boolean equals(Object o) {
asd obj = (asd) o; //se transforma object en esta clase
if(cadena.equals(obj.cadena) && numero==obj.numero) {
return true;
}
return false;
}

public static int getHash(int... fieldHashes) {
int result = 17;
for (int hash : fieldHashes) {
result = 37 * result + hash;
}
return result;
}


//...
}

class hola {
public static void main(String... a) {
asd l = new asd("Hola" , 3);
asd l1 = new asd("Hola" , 3);
System.out.println(l.hashCode());
System.out.println(l1.hashCode());
System.out.println(l1.equals(l));
}
}

Listo,nuestra clase esta preparada para poder ser usada en un hashSet.

Vamos a ver como se usa:

Podemos agregar elementos al HashSet con:
Código: (java) You are not allowed to view links. Register or Login
boolean add(E e) retorna false si el elemento esta repetido.

Código: (java) You are not allowed to view links. Register or Login
void clear() Borra el conjunto.

Código: (java) You are not allowed to view links. Register or Login
boolean contains(Object o)true si el object esta en el conjunto.

Código: (java) You are not allowed to view links. Register or Login
boolean isEmpty()true si el conjunto esta vacio.

Código: (java) You are not allowed to view links. Register or Login
boolean remove(Object o) Elimina un elemento del conjunto. true si se elimina(si estaba previamente).

Código: (java) You are not allowed to view links. Register or Login
int size()retorna la cantidad de elementos del conjunto.

Y recuerden que herada algunos metodos importantes como addAll() que agrega toda una estructura al set.

Bueno y despues lo mismo de siempre:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;
class asd {
private String cadena;
private int numero;
private int hashCode = 0;

public asd(String s, int i) {
cadena = s;
numero = i;
}

public String getString() {
return cadena;
}

public int getInt() {
return numero;
}

public int hashCode() {
if(hashCode == 0) {
hashCode = getHash( cadena.hashCode(), numero);
}
  return hashCode;
}

public boolean equals(Object o) {
asd obj = (asd) o; //se transforma object en esta clase
if(cadena.equals(obj.cadena) && numero==obj.numero) {
return true;
}
return false;
}

public static int getHash(int... fieldHashes) {
int result = 17;
for (int hash : fieldHashes) {
result = 37 * result + hash;
}
return result;
}

public String toString() {
return cadena + " " + numero;
}

//...
}

class hola {
public static void main(String... a) {
asd l = new asd("Hola" , 3);
asd l1 = new asd("Hola" , 3);
Set<asd> conj = new HashSet<asd>();
conj.add(l);
conj.add(l1); //retornara false, no se insertara
System.out.println(conj); //solo mostrara [Hola 3]
int num = 0;
for(asd as : conj) {
num += as.getInt();
}
System.out.println(num); //3 (la suma de todos los numero dentro del conjunto)
}
}

Ya veremos que podemos recorrer un HashSet como si fuera un arreglo (practicamente) usando iteradores, mas adelante.

TreeSet

You are not allowed to view links. Register or Login

TreeSet sigue manteniendo la filosofia de elementos no duplicados, pero en este caso con un orden particular, esta estructura suele ser bastante util. Esta implementado bajo un arbol binario asi que las operacion de busqueda e insercion son mas lentas que en el HashSet.

Si lo que se va a guardar adentro del TreeSet es algo hecho por nosostros tenemos que definir una forma de poder hacer comparaciones, no de igualdad como ya lo veniamos haciendo, sino saber si es mayor o menor. Eso lo vamos a explicar mas adelante en la parte de Comparable y Comparator.

Por el momento vamos a usarlo para clases que ya estan definidas.

A diferencia de HashSet como este conjunto esta ordenado hay un primero y un ultimo, un mayor y un menor y subconjuntos especificos, justamente esos son metodos que podemos usar en TreeSet ademas de los que ya saben.

Metodos como: first(), last(), subSet(), headSet(), tailSet() son algunos de los mas interesantes, pueden ver la documentacion todos los metodos que hay.

LinkedHashSet

You are not allowed to view links. Register or Login

LinkedHashSet por ahora no tiene mucha importancia para nosotros porque no sabemos usar iteradores pero basicamente es igual a HashSet con una unica diferencia.

En HashSet los elementos se iban agregando y se guardaban en un vector cuyo indice era el hashCode del elemento, si de alguna manera intetariamos recorrer eso uno por uno (como no tiene orden) jamas sabriamos cual elemento viene despues de cada uno.

En los TreeSet podiamos saber eso porque cada elemento se comparaba con los demas, aca tambien existe un orden pero en este caso esta dado por como se agregaron los objetos, este oreden es guardado en una lista doblemente vinculada, de todas formas los costos siguen siendo O(1) pero tardan mas tiempo que HashSet.

Puede que sea util en algun caso que se requiera saber como fueron insertados los elementos, pero no mas de eso.

Si observan el constructor no veran ningun metodo adicional dentro de esta clase, son solo constructores.

Antes de terminar con los conjuntos faltaria algo muy importante que son las operaciones entre ellos (union interseccion etc).

De este codigo pueden sacar todas esas cosas:

Código: (java) You are not allowed to view links. Register or Login
import java.util.Set;
import java.util.TreeSet;

public class Main {
  public static <T> Set<T> union(Set<T> setA, Set<T> setB) {
    Set<T> tmp = new TreeSet<T>(setA);
    tmp.addAll(setB);
    return tmp;
  }

  public static <T> Set<T> intersection(Set<T> setA, Set<T> setB) {
    Set<T> tmp = new TreeSet<T>();
    for (T x : setA)
      if (setB.contains(x))
        tmp.add(x);
    return tmp;
  }

  public static <T> Set<T> difference(Set<T> setA, Set<T> setB) {
    Set<T> tmp = new TreeSet<T>(setA);
    tmp.removeAll(setB);
    return tmp;
  }

  public static <T> Set<T> symDifference(Set<T> setA, Set<T> setB) {
    Set<T> tmpA;
    Set<T> tmpB;

    tmpA = union(setA, setB);
    tmpB = intersection(setA, setB);
    return difference(tmpA, tmpB);
  }

  public static <T> boolean isSubset(Set<T> setA, Set<T> setB) {
    return setB.containsAll(setA);
  }

  public static <T> boolean isSuperset(Set<T> setA, Set<T> setB) {
    return setA.containsAll(setB);
  }

  public static void main(String args[]) {
    TreeSet<Character> set1 = new TreeSet<Character>();
    TreeSet<Character> set2 = new TreeSet<Character>();

    set1.add('A');
    set1.add('B');
    set1.add('C');
    set1.add('D');

    set2.add('C');
    set2.add('D');
    set2.add('E');
    set2.add('F');

    System.out.println("set1: " + set1);
    System.out.println("set2: " + set2);

    System.out.println("Union: " + union(set1, set2));
    System.out.println("Intersection: " + intersection(set1, set2));
    System.out.println("Difference (set1 - set2): " + difference(set1, set2));
    System.out.println("Symmetric Difference: " + symDifference(set1, set2));

    TreeSet<Character> set3 = new TreeSet<Character>(set1);

    set3.remove('D');
    System.out.println("set3: " + set3);

    System.out.println("Is set1 a subset of set2? " + isSubset(set1, set3));
    System.out.println("Is set1 a superset of set2? " + isSuperset(set1, set3));
    System.out.println("Is set3 a subset of set1? " + isSubset(set3, set1));
    System.out.println("Is set3 a superset of set1? " + isSuperset(set3, set1));

  }
}
You are not allowed to view links. Register or Login

Queue (implementacion)

Queue (que significa cola o fila) es una interface, normalmente se implementa con una LinkedList

You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login

Bueno no hay mucho que decir si ya se sabe como trabaja una fila, con un codigo bastara.

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;
public class Main {

    public static void main(String... args) {
        Queue<String> queue = new LinkedList<String>();
       
        //se pueden agregar elementos usando add() y si algo sale mal salta una excepcion
        queue.add("Hola1");
       
        //tambien se puede usar offer() y si algo sale mal se devuelve false
        queue.add("Hola2");

        //se elimina y obtiene un elemento de la fila con remove(), si la fila esta vacia habra una excepcion
        System.out.println("Se elimino: " + queue.remove());

        //igual que remove(), pero si algo sale mal retorna false
        System.out.println("se elimino " + queue.poll());

        //se puede verificar el primer elemento que va a salir con element(), si la fila esta vacia habra una excepcion
        System.out.println("element: " + queue.element());

        //igual que element() pero si la fila estaba vacia de devuelve null
        System.out.println("peek: " + queue.peek());
    }
}

Los metodos isEmpty() y size() son heredados de Collection.

PriorityQueue

You are not allowed to view links. Register or Login

Una cola de prioridad no mantiene la filosofia de la cola ordinaria que el primero que entraba era el primero que salia (FIFO). Aca basicamente tenemos una estructura en donde los elementos tienen una prioridad que los hace diferentes (o iguales) a los demas del mismo tipo, esta estructura estara siempre ordena por esta prioridad y el primero en salir es el de mayor prioridad (todas las inserciones son ordenadas y solo se puede extraer el mas priorizado).

Es bastante util mas que nada para mejorar la complejidad de algoritmos como por ejemplo el A* pero normalmente se puede reemplazar por un arreglo o lista ordinarios, hay que saber bien cuando usar esta estructura y se ahorraran bastante complejidad computacional (se implementa sobre un heap binario) asi que las inserciones son en O(log n).

Como la estructura es ordenada cada elemento debe porder distinguirse de los demas (mismo problema que es TreeSet) y es nesesario saber algo que veremos mas adelante sobre Comparable y Comparator.

En caso de ser clases que ya estan implementadas como String o Integer se pueden usar normalmente, los metodos son los mismo que para las colas con la diferencia que el add() o offer() es segun prioridad

ArrayDeque

You are not allowed to view links. Register or Login

ArrayDeque es la implementacion mas usada de la interface Deque que significa double ended queue que a fines practicos es una cola donde se puede sacar o meter por los dos lados.

ArrayDeque funciona mas rapido como pila que la clase Stack y mas rapido como cola que la clase LinkedList.

Basicamente los metodos son los mismos que los de la cola, pero ahora hay dos tipos los de una lado de la cola y los del otro, por ejemplo: offerFirst() y offerLast(). Tambien existe offer() y tienen que mirar bien la API haber que hacen estos sueltos, en este caso es lo mismo que offerLast().

El uso de esta clase ya es meramente por cuestiones de querer ahorrar tiempo computacional gracias a las ventajas de las deques.
« Última modificación: Abril 29, 2012, 10:19:20 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #36 en: Abril 26, 2012, 02:51:59 pm »
HashMap

You are not allowed to view links. Register or Login

HashMap es lo que se usa para representar una tabla de hashes o un mapa. basicamente es una llave o key que esta asosiada a un valor, es como una ampliacion de lo que era un arreglo que cada valor tenia asosiado un numero, aca se asosia otro valor determinado. Por eso lo primero y mas importane es destacar que para definir un Map se requiere el tipo de la llave y luego el del valor:

Código: (java) You are not allowed to view links. Register or Login
Map<String, Integer>
Ahi por ejemplo tenemos llaves String que hacen referencia a valores Integer.

El caso mas real de esta estructura es un diccionario, donde tenermos las llaves que son palabras y el contenido es la definicion, no puede haber palabras repetidas (las llaves son unicas), pero si dos llaves pueden apuntar al mismo valor (sinonimos?) y cada clave solo tiene un valor (no hay ambiguedades).

Un mapa no es una coleccion, sin embargo contiene distintas colecciones como un onjunto de claves (Set<K>), una coleccion de valores (Collection<V>) que forman un conjunto de pares <clave, valor> (Set<Map.Entry<K,V>>). (ya veremos esto ultimo)

Las claves tienen que ser inmutables, no puden cambiar. y pueden ser null.

Como el mapa no es una coleccion para poder usarlo como tal nesesitamos obtener informacion de el para poder iterarlo en algun "formato" de colecion existente, tenemos:

Código: (java) You are not allowed to view links. Register or Login
keySet()retorna una vista del mapa como un conjunto de claves

Código: (java) You are not allowed to view links. Register or Login
values()retorna una vista del mapa como una coleccion de valores del tipo destino

Código: (java) You are not allowed to view links. Register or Login
entrySet()retorna la vista del mapa como un conjunto de parejas clave-valor; son objetos de la clase interna Entry

Algunas de las cosas que podemos hacer con HashMap son:

Código: (java) You are not allowed to view links. Register or Login
void clear()Elimina todos los elementos

Código: (java) You are not allowed to view links. Register or Login
boolean containsKey(Object key)Comprueba si la clave especificada se encuentra.

Código: (java) You are not allowed to view links. Register or Login
boolean containsValue(Object value)Comprueba si el valor especificado se encuentra.

Código: (java) You are not allowed to view links. Register or Login
V get(Object key)Devuelve el valor asociado a la clave especificada o null si no se encontro.

Código: (java) You are not allowed to view links. Register or Login
boolean isEmpty()Comprueba si la colección esta vacia.

Código: (java) You are not allowed to view links. Register or Login
V put(K key, V value)Añade un nuevo par clave-valor al mapa

Código: (java) You are not allowed to view links. Register or Login
V remove(Object key)Elimina el par clave-valor correspondiente a la clave pasada como parametro.

Código: (java) You are not allowed to view links. Register or Login
int size()Devuelve el numero de pares clave-valor que contiene el mapa.

El metodo entrySet() retorna un objeto de la interfaz interna Entry, que representa una pareja clave-valor. Dispone de los siguientes métodos

Código: (java) You are not allowed to view links. Register or Login
getKey()retorna la clave

Código: (java) You are not allowed to view links. Register or Login
getValue()retorna el valor

Código: (java) You are not allowed to view links. Register or Login
setValue(V value)cambia el valor haciéndolo igual a value, y retorna el valor anterior. El cambio se refleja en el mapa original.

Pueden ver You are not allowed to view links. Register or Login la documentacion de esta interaz.

Un pequeño ejemplo:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class AgendaTelefonica {
    // la agenda se guarda en un mapa
    private Map<String,Integer> agenda;

    /**
    * Constructor que deja la agenda vacia
    */
    public AgendaTelefonica() {
        agenda = new HashMap<String,Integer>();
    }

    /**
    * Añadir un nombre con su teléfono
    */
    public void anadeTelefono(String nombre, int telefono) {
        agenda.put(nombre, new Integer(telefono));
    }

    /**
    * Consultar un nombre; retorna el telefono, o 0 si el nombre no existe
    */

    public int consulta (String nombre) {
        Integer tel= agenda.get(nombre);
        if (tel==null) {
            return 0;
        } else {
            return tel.intValue();
        }
    }

    /**
    * Saber si un nombre esta en el diccionario
    */
    public boolean estaIncluido(String nombre) {
        return agenda.containsKey(nombre);
    }

    /**
    * Mostrar la lista de toda la agenda
    */
    public void mostrarNumeros() {
        Set<Map.Entry<String,Integer>>
        lista=agenda.entrySet();
        System.out.println();
        System.out.println("Nombre - Telefono:");
        for (Map.Entry<String,Integer> e:lista) {
            System.out.println(e.getKey()+" - "+e.getValue());
        }
    }
}
You are not allowed to view links. Register or Login

Otro mas:
Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

class Sucursal {
private int codigo;
private String direccion;
private HashMap<Persona, LinkedList<ProductoFinanciero>> pasivo;

public Sucursal(int codigo, String direccion){
this.codigo = codigo;
this.direccion = direccion;
pasivo = new HashMap<Persona, LinkedList<ProductoFinanciero>>();
}

public void addContrato(Persona cliente, ProductoFinanciero producto) {
LinkedList<ProductoFinanciero> productos;
if (! pasivo.containsKey(cliente)) {
productos = new LinkedList<ProductoFinanciero>();
pasivo.put(cliente, productos);
} else {
productos = pasivo.get(cliente);
}
productos.add(producto);
}

public Set<Persona> getClientes(){
return new HashSet<Persona>(pasivo.keySet());
}

public Set<ProductoFinanciero> getProductosContratados(){
Collection<LinkedList<ProductoFinanciero>> productos;
productos = pasivo.values();
Set<ProductoFinanciero> cjtoProductos = new HashSet<ProductoFinanciero>();
for (LinkedList<ProductoFinanciero> lista : productos) {
cjtoProductos.addAll(lista);
}
return cjtoProductos;
}
}
You are not allowed to view links. Register or Login. a este le falta implementar las clases de adentro pero como para que vean como se maneja alcanza.
Ahi miles de ejemplos mas por la web busquenlos y ponganse a probar por su cuenta.

HashTable

You are not allowed to view links. Register or Login

HashTable sera una de esas colecciones a las que tampoco le daremos mucha atencion, es similar a hashmap pero es sincronizada (para entornos multi-hilo) y otra particularidad es que no permite valores null como claves.

De todas formas, solo se nomobra esta coleccion ya que esta practicamente deprecada, lo mejor es usar HashMap cuando sea posible.
 
LinkedHashMap

You are not allowed to view links. Register or Login

Ya vimos esto antes y fue con LinkedHashSet, un conjunto no tenia orden asi que cuando lo recorrieramos uno por uno (que todavia no vimos eso) no podiamos anticipar que iba a venir, usando LinkedHashSet se guardaba el orden de insercion a cambio de un poco de consto adicional, asi podiamos recorrer los elementos en el orden en que fueron insertados.

Aca es lo mismo, el HashMap no tiene orden asi que con esta clase guardamos cual se fue insertando depues de cual y luego cuando se recorra con iteradores podemos saber en que orden apareceran los elementos.

Recordar que esta clase es mas lenta a la hora de añadir pero mas rapida a la hora de acceder.

TreeMap

You are not allowed to view links. Register or Login

Otro que ya lo vimos con TreeSet, y en este caso el orden no es el de entrada sino que nosostros le deciamos como se ordena (como saber si lo que almacena es mas grande o mas chico que otro) en este caso se habla de las claves siempre.

Esta clase es mucho mas costosa para insertar porque tiene que ordenar.

Sera mejor que lean primero que es lo de Comparable y Comparator antes de intentar entender la API.

WeakHashMap

You are not allowed to view links. Register or Login

WeakHashMap es algo complejo (no dificil, sino que es medio especifico para explicar), se usa mas que nada para guardar informacion adicional a un objeto.

Por ejemplo hasta ahora usabamos las llaves para poder hacer referencia a un valor asociado que probablemente es lo que nos importaba, por ejemplo el caso del diccionario que buscamos la palabra y encontramos el significado.

WeakHashMap se usa diferente, es para almacenar informacion extra a un objeto que ya tenemos definido, por ejemplo un objeto con ciertos atributos y que en ocaciones es nesesario agregar algun dato, en ocaciones otro o en ocaciones ninguno, se puede usar aca. El objeto se usa de key y los datos adicionales son el valor dentor del WealHashMap, lo conveniente de esto es que cuando se deja de usar el objeto no tenemos que hacer el metodo finalize() para que la garbage collector tambien borre los datos asociados, porque al estar aca dentro eso se hace solo.

Su uso es importante gracias a esto ultimo, puede usarse como una cache ya que no tenemos que preocuparnos por borrar informacion extra.

You are not allowed to view links. Register or Login que habla un poco mas y muestra un ejemplo de donde se podria usar

IdentityHashMap

You are not allowed to view links. Register or Login

IdentityHashMap es igual a HashMap con una pequeña diferencia, en es de usar equals() para comparar las keys a la hora de hacer operaciones sobre el Map, usa: ==

Nadie sabe como afecta esto a la estructura? es facil si se acuerdan lo de los Strings, vamos a ver el ejemplo con eso mismo.

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Map<String, Integer> ihm = new IdentityHashMap<String, Integer>();
        Map<String, Integer> hm = new HashMap<String, Integer>();
       
        ihm.put("hola", 1);
        ihm.put("hola", 2);
        ihm.put(new String("hola"), 3);
       
        hm.put("hola", 1);
        hm.put("hola", 2);
        hm.put(new String("hola"), 3);


        System.out.println("IdentityHashMap size: " + ihm.keySet().size()); //2
        System.out.println("HashMap size" + hm.keySet().size()); //1

}
}

Ahi les comente cuanto daria en cada caso y porque es esto? el hashMap es facil, metimos 3 "hola" asi que al hacer el equals() los tres son iguales, solo puede haber 1 clave asi que las demas no entran y queda una solo.

IdentityHashMap al hacer las comparaciones con == no esta viende si "hola".equals("hola"), en realidad esta comparando los objetos, y cuando le pasamos: new String("hola") estamos creando una nueva instancia y es diferente por eso entra al Map.

En donde se aplica .... ya sabran xD

Saludos
« Última modificación: Abril 30, 2012, 05:51:53 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #37 en: Abril 26, 2012, 02:56:09 pm »
Iterator

You are not allowed to view links. Register or Login

Este es uno de los dos temas que nos venia quedando pendiente mientras se explicaban las estructturas y son los iteradores.

Los iteradores sirven para poder recorrer una estructura (cualquiera sea) de forma secuencial mas alla si tiene o no orden o forma de acceder a elementos como gets y esas cosas.

La ventaja de usar iteradores es que no hace falta conocer el codigo o la estructura de abajo porque el iterador es el que se encarga de pasr de elemento a elemento.

Hasta ahora habiamos visto el foreach para poder recorrer una estructura de principio a fin, el foreach hace uso de un iterador implicito, pero como desventaja no podemos manejar ese iterador a nuestro antojo (por ejemplo eliminar un elemento).

Un iterador tiene 3 metodos interesantes:

Código: (java) You are not allowed to view links. Register or Login
boolean hasNext()Devuelve true si hay mas elementos para recorrer.

Código: (java) You are not allowed to view links. Register or Login
E next()Devuelve el elemento siguiente.

Código: (java) You are not allowed to view links. Register or Login
void remove()Elimina el elemento que hubiera devuelto el iterador.

Si no se van a eliminar elementos lo mejor es usar foreach porque es mucho mas sencillo de manejar y mas agradable a la vista, si se nesesita recorrer la coleccion e ir decidiendo que elemento se elimina y cual no, ahi lo mejor es usar iteradores, veamos un ejemplo.

Código: (java) You are not allowed to view links. Register or Login
public double getTotal(List<Banco> bancos) {
double dineroTotal = 0;
for (Banco b : bancos) {
dineroTotal += b.getDinero();
}
return dineroTotal;
}

public void cerrarBancos(List<Banco> bancos) {
Iterator<Banco> it = bancos.iterator();//se crea un iterador capaz de iterar sobre la lista
while (it.hasNext()) { //se va a recorrer toda la lista
Banco b = iterator.next(); //se obtiene el elemento actual
if (b.getDeficit() > 10000) { //si ese elemento cumple con la condicion de ser borrado
it.remove(); //se elimina y se sigue recorriendo la lista
}
}
}

Si no quieren usar el while se puede utilizar un for de los tradicionales para iterar con iteradores de esta forma:

Código: (java) You are not allowed to view links. Register or Login
for (Iterator it = bancos.iterator(); it.hasNext();)
Pero es mas engorroso todavia.

Con los iteradores podemos recorrer cualquier coleccion menos los hashMap como ya vimos porque tienen un estructura particualar, la forma de recorrerlo con iteradores es:

Código: (java) You are not allowed to view links. Register or Login
HashMap<Integer, String> hashMap = new HashMap<Integer, String>();

hashMap.put(1,"valor1");
hashMap.put(2,"valor2");
hashMap.put(3,"valor3");

Iterator it = hashMap.entrySet().iterator();
    while (it.hasNext()) {
         Map.Entry me = (Map.Entry)it.next();
         System.out.println(me.getKey() + " " + me.getValue());
    }

Una de las tantas.

ListIterator

You are not allowed to view links. Register or Login

Los iteradores no tenian mucha complejidad porque al ser tan generales es dificil que tengan metodos especificos, ListIterator es una clase mas especifica, no sirve para todas las colecciones pero tiene metodos extra.

Solo sirven para las clases que implementan las interface List, que son las primeras que vimos, ArrayList, LinkedList son las mas importantes.

Los metodos extra??

Código: (java) You are not allowed to view links. Register or Login
void add(E e)Añade un elemento en donde esta el iterador.

Código: (java) You are not allowed to view links. Register or Login
boolean hasPrevious()Igual que hasNext() pero para atras.

Código: (java) You are not allowed to view links. Register or Login
E previous()Igual que next() pero para atras

Código: (java) You are not allowed to view links. Register or Login
int nextIndex()Devuelve el indice del elemento siguiente

Código: (java) You are not allowed to view links. Register or Login
int previousIndex()Igual que nextIndex() pero para atras

Código: (java) You are not allowed to view links. Register or Login
void set(E e) Reemplaza el elemento al que apunta el iterador

Como se habran dado cuanta, para arreglos y listas hay muchas mas cosas que se pueden hacer con los iteradores.

Saludos
« Última modificación: Abril 30, 2012, 06:24:24 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #38 en: Abril 26, 2012, 02:57:42 pm »
Comparable y Comparator

Esta es la ultima cosa que nos quedo pendiente y que se tiene que saber usar a la hora de manejar estructuras ordenadas como lo eran la PriorityQueue, los TreeSet o los TreeMap. Tambien veremos en el siguiente capitulo que dentro del package de java.util hay clases que nos proporcionan metodos para ordenar una estructura.

Para poder ordenar algo de mayor a menor o como sea que se quiera es nesesario que los elementos que componen dicha estructura tengan una forma de poder compararse entre si y decidir si son mayores, iguales o menores.

Hasta ahora vimos ejemplos con clases de Java como lo eran Integer o String, estas clases se pueden comparar una a la otra porque implementan la interface Comparable que les obliga a implementar el metodo

Código: (java) You are not allowed to view links. Register or Login
int compareTo(E e)
Diremos que una estructura que es ordenada gracias a que sus objetos son comparables se ordeno por orden natural.

El metodo compareTo devuelve un entero positivo si la relación es "mayor que", negativo si es "menor que" y cero si son iguales.

Entonces para poder guardar nuestras propias clases en estructuras ordenadas hay que implementar la interface Comparabe y sobreescribir compareTo() escribiendo ahi cuando un objeto es mayor, igual o menor a otro, veamos un ejemplo.

Supongamos que tenemos la clase persona de esta manera:

Código: (java) You are not allowed to view links. Register or Login
class Persona implements Comparable {
private int edad;
private String nombre;
private long ID;

//...

public long getID() {
return ID;
}

public int compareTo(Object o) {
    Persona ob = (Persona) o;
            if(this.ID == ob.getID()) {
        return 0;
            } else if (this.ID < ob.getID()) {
        return -1;
            } else {
        return 1;
            }
}
}

Algo de este estilo esta listo para ser insertado de forma ordenada, (ID seria el documento de la persona, lo puse asi porque por ahi no se entiendo sino).

Supongamos por un momento que dos personas son iguales si s nombre es igual, la forma corracta de hacer el comparaTo es hacer el compareTo de de los dos Strings

Código: (java) You are not allowed to view links. Register or Login
class Persona implements Comparable {
private int edad;
private String nombre;
private long ID;

//...
        public String getNombre() {
            return nombre;
        }

public int compareTo(Object o) {
    Persona p = (Persona) o;
            return this.nombre.compareTo(p.getNombre());
}

}

No se si se llega a ver pero con this.nombre hacemos referencia al String y llamamos a su metodo compareTo

Pero bueno, olvidemos de eso, porque dos personas no son iguales si sus nombres son iguales, la forma corracta es la primera, recuerden que esto es el orden natural (ya se que los ID pueden ser repetidos y que se yo pero supongan que si).

Que pasa si queremos tener un conjunto de personas que este ordenado por edades?

Comparable define el orden natural, asi que esta mal andar sobreescribiendo y esas cosas, se tiene que dejar como esta.

La forma correcta es usar Comparator que es mas bien una clase de apoyo para poder comparar elementos. Si se usa Comparator se llama criterio de ordenacion.

Al implementar dicha interface estamos obligados a sobreescribir el metodo:

Código: (java) You are not allowed to view links. Register or Login
compare(Object o1, Object o2)
El metodo compare devuelve un entero positivo si la relación es "mayor que", negativo si es "menor que" y cero si son iguales.

Comparator esta en java.util no en java.lang como Comparable, asi que si lo van a usar hay que importar el paquete.

Las colecciones que tienen un orden permiten comparadores en sus constructores asi que veamos el ejemplo con TreeSet.

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

class Persona implements Comparable {
private int edad;
private String nombre;
private long ID;

public int getEdad() {
return edad;
}

//...

public int compareTo(Object o) {
Persona p = (Persona) o;
        return this.nombre.compareTo(p.nombre);
}


}

class OrdenarEdad implements Comparator {

    public int compare(Object o1, Object o2) {
    Persona p1 = (Persona) o1;
        Persona p2 = (Persona) o2;
        return p1.getEdad() - p2.getEdad();
    }
}

En este caso con la resta solucionamos todo porque si son iguales tenemos que devolver 0 y lo hacemos y para las otras relaciones tambien anda, sino tendriamos que usar los if. La parte de Comparable hagan de cuenta que ni esta, si se usa un Comparador este tiene mas prioridad que el orden natural.

Ahora se hace algo asi:

Código: (java) You are not allowed to view links. Register or Login
Set personas = new TreeSet(new OrdenarEdad());
Usando el constructor de TreeSet que permite un Comparator ahora si agregamos Personas ahi estaran ordenadas por edad y no por documento como se hubieran ordenado.

Con eso ya pueden manejar bien las estructuras estas que estubimos viendo.

Saludos

« Última modificación: Abril 30, 2012, 07:00:17 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #39 en: Abril 26, 2012, 02:57:56 pm »
Collections y Arrays

You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login

Tanto Collections (no confundir con la interface Collection) como Arrays son clases utilitarias que tienen diversos algoritmos para apllicar a las estructuras que ya vimos.

Collections proporciona algoritmos para cualquier estructura de la interface Collection (los que acabamos de ver) y Arrays son algoritmos para los viejos arreglos, los que se definian con corchetes y no eran clases.

Arrays tiene basicamente 4 metodos que estan sobrecargados mil veces cada uno, los cuatro son: busqueda, comparacion, inicializacion/asignacion y ordenacion.

Permite hacer busquedas de un cierto elemento en un arreglo mediente binarySearch()
Pueden ver si dos arreglos son iguales o no con equals()
Pueden hacer asignaciones en gran medida (todo un arreglo se vuelve todo este otro o parte de el) con fill()
Pueden ordenar arreglos con sort()

Todos estos metodos son static asi que no hace falta instancias de la clase, solo se importa y se usa (como se hacia con Math). No es posible instanciar la clase porque tiene constructor privado.

Otra cosa interesante es que permite transformar un arreglo de estos "ordinarios" en una List que despues podemos trasnformar en ArrayList o LinkedList con uso del polimorfismo.

Collections por otro lado dijimos que era para las estructuras que vimos ahora, entre los metodos mas importantes tenemos:

Código: (java) You are not allowed to view links. Register or Login
int binarySearch(List list, Object key)Busca un elemento en una lista ORDENADA, devuelve un entero positivo indicando el indice donde se encuentra el elemento o negativo si no se encontro.

Código: (java) You are not allowed to view links. Register or Login
int frequency(Collection c, Object o)Devuelve el numero de veces que se repite un elemento en la coleccion

Código: (java) You are not allowed to view links. Register or Login
Object max(Collection coll)Devuelve el mayor elemento

Código: (java) You are not allowed to view links. Register or Login
Object min(Collection coll)Devuelve el menor elemento

Código: (java) You are not allowed to view links. Register or Login
boolean replaceAll(List list, Object oldVal, Object newVal)Reemplaza todas las ocurrencias de un elemento por otro

Código: (java) You are not allowed to view links. Register or Login
void reverse(List list)Invierte la lista

Código: (java) You are not allowed to view links. Register or Login
void shuffle(List list)Modifica le disposicion de los elemntos de forma aleatoria

Código: (java) You are not allowed to view links. Register or Login
void sort(List list)Ordena una lista

Hay algunos mas, unos que nos permiten transformar una coleccion en inmutable (que no se pueda cambiar) y varios mas.

Hay una variante del metodo sort a la que se le puede pasar un Comparator para que no ordene usando Comparable.

Aca tambien son todos static y ya saben como va la cosa para usarlos.

Saludos
« Última modificación: Abril 30, 2012, 07:01:28 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #40 en: Abril 27, 2012, 02:06:48 pm »
Identificando que estructura hay que usar

Este tema es mas importante que conocer todas las estructuras, porque si elegimos mal puede que tengamos que hacer muchos pasos de mas para interactuar con los datos.

Aca les dejo una imagen que los orienta sobre cual estructura elegir.


Puede que se hayan quedado con ganas de muchas mas estructuras como lo son los heaps, arboles, grafos o quien sabe cual se les estan ocurriendo a ustedes ahora.

Por el momento no veremos mas, asi que si queres saber mas acerca de estructuras de datos te dejo este libro para que lo consultes:

You are not allowed to view links. Register or Login

Esta muy completo, pero scaneado.

Saludos
« Última modificación: Abril 29, 2012, 05:26:57 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #41 en: Abril 29, 2012, 05:26:08 pm »
Si mal no me parece todos los codigos que se pusieron hasta aca deberian de entenderse todos con todos los conceptos a excepcion de algunos que tienen cosas como try, catch, throws, Thrownable, Exception y esas cosas.

Ese sera el siguiente tema que veremos, pero antes como ya hemos visto bastante de los package java.lang y java.util de Java me gustaria terminar de comentarles todo lo que tienen, aunque sea lo mas importante.

Una ves que veamos eso, vamos a explicar bien el tema del control de errores en Java y despues nos vamos a meter de lleno en el package java.io que es para el manejo de archivos y datos.

Por consiguiente a partir de ahora veremos todos temas sueltos que para finalizar con estos 2 package que son los mas utilizados.

java.util

Terminemos de ver este paquete, hasta ahora hemos visto todas las colecciones, con sus iteradores y comparadores y las clases que tenian algoritmos. Tambien hemos visto la clase Scanner que sirve para leer datos desde la entrada standar como lo eran Strings o por ejemplo int, double, etc. Aunqu no la vimos muy en profundidad fue mas o menos lo que se nesesita y lo demas esta en la documentacion. Aunque no paresca eso es mucho, es casi todo el paquete, lo que queda por ver es lo siguiente:

Calendar, GregorianCalendar, Date, Locale, TimeZone y SimpleTimeZone que manejan fechas y cosas.

Random para generar numero aleatorios.

Timer y TimerTask para realizar tareas sincronizadas.

Observable usado para monitorear el estado de un objeto.

ServiceLoader que se usa para cargar plugins en tiempo de ejecucion.

Veamos una imagen que muestra un poco las clases que siguen despues de las colecciones dentro de este paquete



Ahi no estan todas, al igual que sucedio cuando vimos las colecciones, pero da una idea general de que clases existen. Si quieren ver todas tienen la You are not allowed to view links. Register or Login.

Empecemos a nombrar algunas cosas basicas, asi como Vector y HashTable estaban deprecadas o casi deprecadas, es decir que ya no se deben usar mas porque hay otra que la sustituye y hace mejor su trabajo, existen otras clases que tambien debemos intentar no usar porque estan deprecadas, la mas comun es StringTokenizer, esta clase permite agarra un String y transformarlo en un array partiendolo por donde nosostros queramos (por ejemplo por los espacion en blanco devuelve cada palabra del String) esta clase ya no se usa, esta en al API, esta en la documentacion y en mil manuales de internet, pero no hay que usarla mas, ahora se usa el metodo split() que tienen los String, y ya lo mencionamos en este tutorial.

La clase Date se usa como ya se daran cuenta para el manejo de fechas y esas cosas, tambien hay que intentar no usarla, esta deprecada, ahora se usa Calendar.

Dictionary<K,V> a que les suena? y si, es otra antecesora de HashMap, pero a diferencia de HashTable esta si esta deprecada totalmente, no debe usarse.

Porque se mantienen si no sirven? para que los programas viejos pueden seguir compilando, si se sacan de la API todos estos programas que las usan tienen que ser modificados totalmente y eso es muy costoso.

Lo primero que vamos a ver es Timer y TimerTask, estas clases se usan para cuando queremos realizar una tarea cada cierto tiempo o cuando queremos realizar una tarea dentro de un cierto tiempo.

El ejemplo clasico es el del reloj, cada 1 segundo queremos hacer una tarea que es actualizar el reloj.

La clase Timer tiene un metodo schedule que se usa para agregar tareas, si se fijan hay mil formas de crearlas, es como les decia para decir cuando queremos que empieze y cuantas veces etc.

Cada tarea agregada a Timer tiene que ser una clase que herede de TimerTask, nos obliga a implementar run() que es donde va lo que se quiere hacer.

Timer es una clase que se maneja con Threads(hilos) que todavia no los vimos pero basicamente es hacer una tarea a la par de otra, por eso si ejecutamos un timer nuestro programa sigue su ejecucion y no es que espera que termine.

Si la computadora tiene mucho trabajo y tarda en atender nuestra tarea vamos a empezar a tener inconsistencia, por ejemplo supongamos que queremos cada un segundo hacer algo, si la PC atiendo esa tarea a el 1.1 segundo ya tenemos 0.1 segundo atrasada la tarea, si ahora tarda 1.3 segundo en atender la tarea estamos atrasados 0.4 y asi hasta que sea cualquier cosa, por eso tambien esta el metodo scheduleAtFixedRate() que toma como referencia cuando se parte, entonces si tardamos 1.1 en la primer tarea, ahora en ves de esperar un segundo para atender y poder fallar por algo, se va a atender en 0.9 por eso este metodo es conveniete para la mayoria de las cosas.

Vamos a ver un ejemplo:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;
 
class Reloj {

Timer timer = new Timer();
public int segundos;

public Reloj() {
try {
Start(1);
} catch (Exception err) {}
System.out.println("Hola");
}

public static void main(String... args) {
new Reloj();
}
 
// clase interna que representa una tarea
class MiTarea extends TimerTask {
public void run() {
segundos++;
System.out.println(segundos);
if(segundos==10) Stop();
}
}
 
public void Start(int millSeg) throws Exception {
timer.scheduleAtFixedRate(new MiTarea(), 0, millSeg * 1000);
}
 
public void Stop() {
timer.cancel();
}
 
    public void Reset() {
timer.cancel();
segundos = 0;
}
}

Un contador de segundo hasta 10 que luego termina, vamos a observar algunar cosas, lo primero es que despues del Start() hay un "hola" y si ejecutan el programa ese hola sale casi primero, eso es por lo que hablaba de los hilos, el timer se ejecuta aparte, es como un programa nuevo y se sigue con el nuestro, por eso es que se ejecuta tan rapido y no espara a que termine Timer.

Segundo, vean que la tarea es una clase interna que hereda TimerTask, en este caso es muy como usar clases internas para definir las tareas porque no tendria sentido definir tareas en otros archivos por ejemplo.

Fijense que Start() esta entre un bloque try, eso es porque en la definicion del metodo indicamos que puede lanzar un fallo (throws) ya les dije que es el tema que viene.

Código: (java) You are not allowed to view links. Register or Login
timer.scheduleAtFixedRate(new MiTarea(), 0, millSeg * 1000);
Se va a sincronizar desde el principio y no cada ves, la tarea es MiTarea, arranca dentro de 0 milisegundo y hacela cada tantos segundos. El numero que le pasamos esta en milisegundo asi que hay que multiplicar por 1000 para que sean segundos reales.

Dentro de la clase interna, dentro del metodo run() es donde pueden programar lo que quieren que se haga.

Pueden agregar mas tareas al mismo Timer llamando devuelta a el metodo e indicando la tarea, pueden crear mas clases internas que definen otras tareas tambien. Y no hace falta que finalicen una tarea, la pueden dejar andando para siempre.

Fijense que tambien ademas de indicar dentro de cuantos segundo queremos que arranque tambien podemos pasarle un objeto Date, para indicar la fecha en que queremos que arranque.

Aca la You are not allowed to view links. Register or Login y de You are not allowed to view links. Register or Login.


en construccion

Calendar, GregorianCalendar, Date, Locale, TimeZone y SimpleTimeZone que manejan fechas y cosas.

Random para generar numero aleatorios.

Observable usado para monitorear el estado de un objeto.

ServiceLoader que se usa para cargar plugins en tiempo de ejecucion.


java.lang

Este package es el mas popular y el mas inpopular a la vez, el mas popular porque tiene mil cosas que nos sirven, y el mas inpopular porque como no hace falta importarlo para usarlo nadie lo registra xD.

Que hemos visto hasta ahora de este package?

Bastantes cosas, las interfaces Cloneable, Iterable y Comparable. Las clases envoltorio como lo eran Integer, Character y demas, las clases para representar cadenas: String, StringBuffer y StringBuilder. Vimos la clase para hacer operaciones matematicas Math y aunque no la vimos mencionamos de que trataba StrictMath. Vimos la clase Class cuando habalmos de getClass y algunas de las cosas que nos permitia hacer. Vimos lo que son los Enum

Que queda por ver? casi nada por suerte, teniendo en cuanta que no veremos nada de Threads ni de excepciones porque se veran mas adelante lo que queda se limita a:

Process y Runtime que lo usaremos para ejecutar programas ajenos al nuestro.

Y no veremos mas ya que lo que hay o bien no es muy usado, o es usado a bajo nivel cosa que el programador no se da ni cuenta (como lo era StrictMath por ejemplo) o son cosas relacionadas con Threads que todavia no lo vimos.

Pueden ver todo lo que tiene en la You are not allowed to view links. Register or Login

Esto lo veremos rapido, basicamente la clase Runtime describe algo que se esta ejecutando y tiene un metodo exec() que sirve para ejecutar lo que serian comandos ordinarios en la consola, exec() devuelve una instancia de Process que sirve para pder manejar ese proceso que se creo y poder obtener informacion de el.

Hay que tener en cuanta que si estamos usando esto perdemos la caracteristica de ser multiplataforma, por eso hay que usarlo solo cuando sea nesesario o bien, hacer un manejo en nuetro programa para que reconosca la plataforma y ejecutar diferentes exec() depende de esta, pero eso es algo medio feo, de todas formas veamos como funciona.

Código: (java) You are not allowed to view links. Register or Login
public class Prueba {
   
    public Prueba() {
        try {
            Process p=Runtime.getRuntime().exec ("notepad.exe");
        }
        catch (Exception e) {}
    }

    public static void main(String... args) {
        new Prueba();
    }
}

El string dentro de exec() es como si se escribe directo en la consola (de cualquier sistema operativo). Asi que ahi tienen para poder usar.

No vamos a ver nada mas de java.lang, por lo menos por ahora.

java.math

No hay que confundirse, existia una clase que era java.lang.Math que sirve para hacer calculos y esas cosas. Esto que vemos ahora es un package nuevo, que solo tiene 2 clases. Estas clases heredan de Number, una clase de java.lang que era la padre de las clases Integer y demas, en este package existen las clases llamadas BigDecimal y BigInteger, y vendrian a cerrar el manejo de numeros en Java.

Que son estas clases? BigInteger es una clase envoltorio de int al igual que Integer, y BigDecimal lo es de double, que las diferencia de las que ya existen?, estas clases son para manejar gran presicion, pueden ser numero muy grandes o numeros muy pequeños (en el caso de la coma en BigDecimal). La capacidad de estos numeros es ILIMITADA (osea, depende de la memoria asignada a la JVM pero para casos practicos es ilimitada) y podemos hacer cualquier operacion.

Vamos a ver como manejar estos numeros.

en construccion

Nota final:

Java al igual que cualquier cosa se va actualizando, la API va cambiando y por ahi cosas que vemos aca estan ya deprecadas o hay otras formas de hacerlas. Sin embargo la base es la misma y eso nunca cambia, a partir de ahora en el curso ya vamos a dejar de lado un poco lo que es programacion (porque ya casi se vio todo) y se va a ver un poco mas lo que es manejo de la API. De todas formas lo mejor siempre es consultar la documentacion oficial.

Actualmente Java esta en su version 7 y la ultima documentacion es: You are not allowed to view links. Register or Login. A lo largo de este tutorial se cito documentacion especifica y en algunos casos son versiones viejas, asi que lo mejor es que consulten aca la nueva, y mas adelante investiguen cual es la version actual de Java y vean esa documentacion.

Saludos
« Última modificación: ſeptiembre 29, 2012, 07:34:37 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #42 en: Mayo 01, 2012, 01:43:41 am »
Ejemplo de donde NO usar herencia

Supongamos que tenemos que diseñar las clases necesirias para definir el compartamiento de arrays (podemos usar arraylist) de tres tipos:

1. Simple: que inserte elementos y saque elementos enteros.
2. Positivo: si el elemnetos a insertar es un entero positivo se comporta igual que el simple, sino decimos que no se puede
3. Seguro: Al iniciarlizarlo se tiene que darle un string que es la password, cada ves que se quiere insertar un elemento la va a pedir si la password es correcta se comporta igual que el simple, sino no deja insertar.


Con lo que ya saben un diseño aceptable seria algo asi:

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

interface IArray {
int get(int index);
void put(int elem, int index);
}


class ArraySimple implements IArray {
private List<Integer> arreglo = new ArrayList<Integer>();

public int get(int index) {
return arreglo.get(index);
}

public void put(int elem, int index) {
arreglo.add(index, elem);
}

}


class ArrayPositivo extends ArraySimple {

public void put(int elem, int index) {
if(elem>0)
super.put(elem, index);
else
System.out.println("No se puede");
}
}

class ArraySeguro extends ArraySimple {
private String password;

public ArraySeguro(String password) {
this.password = password;
}

public void put(int elem, int index, String pass) {
if(pass.equals(password))
super.put(elem, index);
else
System.out.println("No se puede");
}
}

Dejando de lado si el codigo esta medio bien o mal lo que importa es el diseño.

Una interface que define los metodos que tienen los arreglos (que podria ser una clase abstracta ya que el metodo get es siempre igual pero para el ejemplo vamos a hacerlo asi).

Una clase que implementa la interface que es la Simple, y dos clases hijas que son la positiva y la segura dado que se comportan similar.

Bien alguien nota algo raro?? que este mal??

Bueno, en la clase arreglo seguro esta el problema, se supone que si yo creo un arreglo seguro solo puedo insertar elemento si se la contraseña, pero como esta puesto el diseño de clases es posible dede el main crear un arreglo seguro con una password que no conoscamos y insertar igual, porque como la clase es hija de arreglo simple heredo el metodo get sin validacion de password, y se puede llamar este metodo desde afuera dado que es publico.

Es mas comunde la que aparenta ver casos como estos en programas, en los que no es una herencia lo que tenemso que hacer si bien pareciera solucionarlo.

Que es lo que hay que hacer?

Herdar si, pero de algo que carezca de comportamiento asi no queda codigo que pueda arruinarnos el diseño, en este caso heredariamos de la interface en ves de la clase simple, y en ves de heredar una arreglo simple lo vamos a componer de una arreglo simple.

Código: (java) You are not allowed to view links. Register or Login
import java.util.*;

interface IArray {
int get(int index);
void put(int elem, int index);
}


class ArraySimple implements IArray {
private List<Integer> arreglo = new ArrayList<Integer>();

public int get(int index) {
return arreglo.get(index);
}

public void put(int elem, int index) {
arreglo.add(index, elem);
}

}


class ArrayPositivo extends ArraySimple {

public void put(int elem, int index) {
if(elem>0)
super.put(elem, index);
else
System.out.println("No se puede");
}
}

class ArraySeguro implements IArray {
private String password;
private ArraySimple arreglo;

public ArraySeguro(String password) {
this.password = password;
this.arreglo = new ArraySimple()
}

public int get(int index) {
return arreglo.get(index);
}

        public void put(int elem, int index){
                System.out.println("No se puede");
        }

public void put(int elem, int index, String pass) {
if(pass.equals(password))
arreglo.put(elem, index);
else
System.out.println("No se puede");
}
}

Ese seria el diseño correcto (o uno de los aceptables) de clases.

Es muy importante identificar las composiciones y no hacer herencia en esos casos.

Saludos
« Última modificación: Octubre 01, 2012, 05:03:00 pm por WaesWaes »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re:JAVA desde CERO
« Respuesta #43 en: ſeptiembre 29, 2012, 08:54:36 pm »
Por hacer:

Diagrama de clases
try catch finally y throws con excepcines bien explicado
Ficheros, stream de I/O y Serialización


xx
JAVA desde cero

Iniciado por vVegeta

73 Respuestas
22716 Vistas
Último mensaje ſeptiembre 08, 2008, 04:28:32 pm
por WaesWaes
xx
PHP desde cero***

Iniciado por buenasbikes

1 Respuestas
2012 Vistas
Último mensaje Noviembre 25, 2006, 07:13:42 pm
por ||Ray||
xx
Desde Cero

Iniciado por alzala

16 Respuestas
6285 Vistas
Último mensaje ſeptiembre 24, 2007, 06:51:02 am
por TXS
xx
Esteganografía Desde Cero.

Iniciado por Xionex

6 Respuestas
3704 Vistas
Último mensaje Agosto 12, 2009, 10:00:06 am
por Xionex
xx
Crackeo desde cero

Iniciado por maximunspider

14 Respuestas
19364 Vistas
Último mensaje Mayo 17, 2011, 06:08:11 am
por jep
exclamation
Empezar PHP desde CERO

Iniciado por tabi1

7 Respuestas
2428 Vistas
Último mensaje Agosto 21, 2012, 03:54:00 pm
por comcom.com
exclamation
Aprendiendo H++ desde cero...

Iniciado por Sthefano02

2 Respuestas
1508 Vistas
Último mensaje Octubre 07, 2010, 02:48:00 pm
por Sthefano02
xx
Desde CEro En linux

Iniciado por teufelkrieg

1 Respuestas
1342 Vistas
Último mensaje Enero 03, 2007, 06:29:44 pm
por rafaelsk
xx
XHTML - desde Cero

Iniciado por an7rax

0 Respuestas
1617 Vistas
Último mensaje Mayo 22, 2009, 05:10:21 pm
por an7rax
resuelto
Taller de CSS Aprendiendo desde Cero

Iniciado por carlmycol

28 Respuestas
22510 Vistas
Último mensaje Abril 15, 2013, 08:34:59 pm
por lfacul