Está en la página 1de 79

UNIVERSIDAD POLITÉCNICA DE MADRID

ESCUELA UNIVERSITARIA DE INFORMÁTICA


LENGUAJES, PROYECTOS Y SISTEMAS INFORMÁTICOS

Tema 7. PROGRAMACIÓN
PARAMETRIZADA

PROGRAMACIÓN ORIENTADA A OBJETOS AVANZADA


GRADO EN INGENIERÍA DEL SOFTWARE

© Adolfo Yela Ruiz y Luis Fernández Muñoz


OBJETIVOS
Presentar cómo crear y utilizar clases
parametrizadas en el lenguaje Java.

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 1


ÍNDICE
1. Introducción
2. Clases genéricas
3. Parámetros limitados
4. Parámetros comodines
5. Métodos genéricos
CASO DE ESTUDIO:
Colecciones

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 2


1. INTRODUCCIÓN
Genéricos:
• A partir de la JDK 1.5 se pueden declarar clases, interfaces y
métodos parametrizados, mediante los parámetros de tipo
(también llamados variables de tipo).
• Las clases parametrizadas se denominan clases genéricas; y los
métodos parametrizados se denominan métodos genéricos.
• Los genéricos son útiles para definir clases cuyos atributos puedan
ser de cualquier clase, y para definir métodos que puedan recibir
argumentos y devolver resultados de cualquier clase.
• Antes de la aparición de los genéricos, esto se conseguía
declarando los atributos de estas clases y los argumentos de estos
métodos con el tipo más débil posible, por ejemplo, Object.

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 3


1. INTRODUCCIÓN
• Frente a esta solución, los genéricos tienen las siguientes ventajas:
• proporcionan una comprobación estricta de tipos en tiempo
de compilación;
• su uso no necesita comprobación de tipos en tiempo de
ejecución;
• producen código más robusto y, en consecuencia, aumentan la
facilidad del mantenimiento de los programas.
Ejemplo
Se desea definir una clase PilaAcotada que pueda albergar objetos
que sean de la misma clase, pero que esa clase pueda ser
cualquiera;

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 4


1. INTRODUCCIÓN
Ej.
public class PilaAcotada {
private Object[] elementos;
private int cuantos;
public PilaAcotada(int tamaño) {
elementos = new Object[tamaño];
cuantos = 0;
}
public void meter(Object elemento) {
elementos[cuantos++] = elemento;
}
public Object sacar() {
return elementos[--cuantos];
}
public boolean vacia() {
return cuantos == 0;
}
public boolean llena() {
return cuantos == elementos.length;
}
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 5
1. INTRODUCCIÓN
• Con esta solución es necesario convertir la dirección devuelta por
el método sacar(), que es de la clase Object, a una dirección de la
clase concreta mediante el operador de conversión de tipos (cast).
• Al sacar un elemento existe la posibilidad de que se produzca un
error de conversión de tipos en tiempo de ejecución al sacar los
elementos, que no es detectado en tiempo de compilación, si los
objetos que se meten en la pila son de distinta clase de la que se
espera que sean al sacarlos.

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 6


1. INTRODUCCIÓN
public static void main(String[] args) {
PilaAcotada pilaIntervalos = new PilaAcotada(10);
Intervalo intervalo1 = new Intervalo(1, 2);
pilaIntervalos.meter(intervalo1);
Intervalo intervalo2 = new Intervalo(3, 4);
pilaIntervalos.meter(intervalo2);
intervalo1 = (Intervalo) pilaIntervalos.sacar();
System.out.println(intervalo1);
intervalo2 = (Intervalo) pilaIntervalos.sacar();
System.out.println(intervalo2);
System.out.println("----------------------------");
PilaAcotada pilaEnteros = new PilaAcotada(10);
Integer i1 = new Integer(4);
pilaEnteros.meter(i1);
Integer i2 = new Integer(7);
pilaEnteros.meter(i2);
i1 = (Integer) pilaEnteros.sacar();
System.out.println(i1);
i2 = (Integer) pilaEnteros.sacar();
System.out.println(i2);
pilaEnteros.meter(intervalo1);
i1 = (Integer) pilaEnteros.sacar(); // ERROR DE EJECUCION
System.out.println(i1);
}
} Tema 7. PROGRAMACIÓN PARAMETRIZADA - 7
1. INTRODUCCIÓN
[3, 4]
[1, 2]
----------------------------
7
4
Exception in thread "main" java.lang.ClassCastException:
pooa.util1.Intervalo cannot be cast to java.lang.Integer
at pooa.util1.PilaAcotada.main(PilaAcotada.java:55)

• Estos problemas se pueden resolver mediante la declaración de


una clase parametrizada, que permita declarar la clase de los
elementos de la pila como un parámetro de tipo.

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 8


2. CLASES GENÉRICAS
SINTAXIS:
class <clase><<parámetro1>,…,<parámetroN>> {

}
• donde los identificadores encerrados entre < y > son los
parámetros de tipo.
• Los parámetros de tipo pueden usarse dentro de la clase
parametrizada para declarar el tipo de sus atributos, argumentos de
sus métodos, o objetos locales de sus métodos.
• Estos parámetros de tipo (formales) se especifican posteriormente
con un tipo concreto (actual) en la instanciación de un objeto de la
clase parametrizada o al declarar una clase hija de la clase
parametrizada, lo que produce la encarnación de la clase
parametrizada, que se convierte en una clase concreta, proceso que
se realiza en tiempo de compilación. Tema 7. PROGRAMACIÓN PARAMETRIZADA - 9
2. CLASES GENÉRICAS
Ej.
public class PilaAcotada<Elemento> {
private Elemento[] elementos;
private int cuantos;
public PilaAcotada(int tamaño) {
elementos = (Elemento[]) new Object[tamaño];
cuantos = 0;
}
public void meter(Elemento elemento) {
elementos[cuantos++] = elemento;
}
public Elemento sacar() {
return elementos[--cuantos];
}
public boolean vacia() {
return cuantos == 0;
}
public boolean llena() {
return cuantos == elementos.length;
}
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 10
2. CLASES GENÉRICAS
• Con esta solución NO es necesario convertir la dirección devuelta
por el método sacar() a una dirección de la clase concreta mediante
el operador de conversión de tipos (cast).
• Al sacar un elemento NO existe la posibilidad de que se produzca
un error de conversión de tipos en tiempo de ejecución al sacar los
elementos, porque el error es detectado en tiempo de compilación,
si se trata de meter elementos que no son de la clase adecuada.

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 11


2. CLASES GENÉRICAS
public static void main(String[] args) {
// ENCARNACION DE LA CLASE PARAMETRIZADA
PilaAcotada<Intervalo> pilaIntervalos = new PilaAcotada<Intervalo>(10);
Intervalo intervalo1 = new Intervalo(1, 2);
pilaIntervalos.meter(intervalo1);
Intervalo intervalo2 = new Intervalo(3, 4);
pilaIntervalos.meter(intervalo2);
intervalo1 = pilaIntervalos.sacar();
System.out.println(intervalo1);
intervalo2 = pilaIntervalos.sacar();
System.out.println(intervalo2);
System.out.println("----------------------------");
// ENCARNACION DE LA CLASE PARAMETRIZADA
PilaAcotada<Integer> pilaEnteros = new PilaAcotada<Integer>(10);
Integer i1 = new Integer(4);
pilaEnteros.meter(i1);
Integer i2 = new Integer(7);
pilaEnteros.meter(i2);
i1 = pilaEnteros.sacar();
System.out.println(i1);
i2 = pilaEnteros.sacar();
System.out.println(i2);
pilaEnteros.meter(intervalo1); // ERROR DE COMPILACION
i1 = pilaEnteros.sacar();
System.out.println(i1);
}
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 12
2. CLASES GENÉRICAS
• en la definición de una clase pueden usarse clases parametrizadas;
Ej.
public class Lista<Elemento> {
private Nodo<Elemento> inicio = null;
private Nodo<Elemento> fin = null;
private int longitud = 0;
Nodo<Elemento> getInicio() {
return inicio;
}
public int size() {
return longitud;
}
public boolean isEmpty() {
return inicio == null;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 13


2. CLASES GENÉRICAS
public Iterador<Elemento> iterador() {
return new Iterador<Elemento>(this);
}
public Elemento get(int posicion) {
Nodo<Elemento> nodo = inicio;
for (int i = 0; i < posicion; i++) {
nodo = nodo.next();
}
return nodo.getElemento();
}
public void add(Elemento elemento) {
Nodo<Elemento> nuevo = new Nodo<Elemento>(elemento);
if (fin == null) {
inicio = nuevo;
} else {
fin.enlazar(nuevo);
}
fin = nuevo;
longitud++;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 14


2. CLASES GENÉRICAS
public void remove(Elemento elemento) {
Nodo<Elemento> anterior = null;
Nodo<Elemento> actual = inicio;
while (!actual.tienes(elemento)) {
anterior = actual;
actual = actual.next();
}
if (anterior == null) {
inicio = actual.next();
} else {
anterior.enlazar(actual.next());
}
if (actual == fin) {
fin = anterior;
}
longitud--;
}

public void clear() {


inicio = null;
fin = null;
longitud = 0;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 15


2. CLASES GENÉRICAS
public Lista<Elemento> clone() {
Lista<Elemento> lista = new Lista<Elemento>();
if (!this.isEmpty()) {
Iterador<Elemento> iterador = this.iterador();
while (iterador.hasNext()) {
lista.add(iterador.next());
}
}
return lista;
}
public String toString() {
String cadena = "{";
Iterador<Elemento> iterador = this.iterador();
if (iterador.hasNext()) {
cadena += iterador.next();
}
while (iterador.hasNext()) {
cadena += "; " + iterador.next();
}
return cadena + "}";
}
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 16


2. CLASES GENÉRICAS
class Nodo<Elemento> {
private Elemento elemento;
private Nodo<Elemento> siguiente;

public Nodo(Elemento elemento) {


this.elemento = elemento;
this.siguiente = null;
}
public Elemento getElemento() {
return elemento;
}
public void enlazar(Nodo<Elemento> nodo) {
this.siguiente = nodo;
}
public boolean tienes(Elemento elemento) {
return this.elemento == elemento;
}
public Nodo<Elemento> next() {
return siguiente;
}
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 17
2. CLASES GENÉRICAS
public class Iterador<Elemento> {
private Nodo<Elemento> actual;
public Iterador(Lista<Elemento> lista){
this.actual = lista.getInicio();
}
public boolean hasNext(){
return actual != null;
}
public Elemento next() {
Elemento elemento = actual.getElemento();
actual = actual.next();
return elemento;
}
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 18


2. CLASES GENÉRICAS
public static void main(String[] args) {
Integer uno = new Integer(1);
Integer dos = new Integer(2);
Integer tres = new Integer(3);
Lista<Integer> listaEnteros = new Lista<Integer>();
listaEnteros.add(uno);
listaEnteros.add(dos);
listaEnteros.add(tres);
System.out.println(listaEnteros);

Intervalo intervalo1 = new Intervalo(uno, dos);


Intervalo intervalo2 = new Intervalo(uno, tres);
Intervalo intervalo3 = new Intervalo(dos, tres);
Lista<Intervalo> listaIntervalos1 = new Lista<Intervalo>();
listaIntervalos1.add(intervalo1);
listaIntervalos1.add(intervalo2);
listaIntervalos1.add(intervalo3);
System.out.println("----------------------------");
System.out.println(listaIntervalos1);

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 19


2. CLASES GENÉRICAS
intervalo1 = new Intervalo(tres, dos);
intervalo2 = new Intervalo(tres, uno);
intervalo3 = new Intervalo(dos, uno);
Lista<Intervalo> listaIntervalos2 = new Lista<Intervalo>();
listaIntervalos2.add(intervalo1);
listaIntervalos2.add(intervalo2);
listaIntervalos2.add(intervalo3);
Lista<Lista<Intervalo>> listaListas =
new Lista<Lista<Intervalo>>();
listaListas.add(listaIntervalos1);
listaListas.add(listaIntervalos2);
System.out.println("----------------------------");
System.out.println(listaListas);
}
}

{1; 2; 3}
----------------------------
{[1, 2]; [1, 3]; [2, 3]}
----------------------------
{{[1, 2]; [1, 3]; [2, 3]}; {[3, 2]; [3, 1]; [2, 1]}}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 20


2. CLASES GENÉRICAS
• Por razones de compatibilidad con códigos anteriores a la JDK 1.5,
está permitido el uso de las clases parametrizadas sin especificar sus
parámetros, aunque el compilador genera un aviso; estas clases se
denominan tipos crudos (raw types).
Lista lista = new Lista(); // AVISO

• Se puede asignar una referencia de una clase parametrizada a un


tipo crudo, y viceversa.
Lista lista = new Lista<Integer>(); // AVISO
Lista<Integer> lista = new Lista(); // AVISO

• Una utilidad de los tipos crudos es poder crear vectores de objetos


de clases parametrizadas, lo cual Java no permite en la actualidad;
Lista<Integer>[] lista = new Lista<Integer>[10]; // ERROR
Lista<Integer>[] lista = new Lista[10]; // AVISO

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 21


2. CLASES GENÉRICAS
• se pueden definir clases parametrizadas con varios parámetros de
tipo;
Ej.
class Item<Clave, Valor> {
private Clave clave;
private Valor valor;
Item(Clave clave, Valor valor) {
this.clave = clave;
this.valor = valor;
}
Clave getClave() {
return clave;
}
Valor getValor() {
return valor;
}
void setValor(Valor valor) {
this.valor = valor;
}
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 22
2. CLASES GENÉRICAS
public class Map<Clave, Valor> {
private static final int CAPACIDAD = 8191;
private Lista<Item<Clave, Valor>>[] listas = // AVISO
new Lista[CAPACIDAD];
public Valor put(Clave clave, Valor valor) {
int i = this.hash(clave);
if (listas[i] == null) {
listas[i] = new Lista<Item<Clave, Valor>>();
} else {
Iterador<Item<Clave, Valor>> iterador = listas[i].iterador();
while (iterador.hasNext()) {
Item<Clave, Valor> item = iterador.next();
if (clave.equals(item.getClave())) {
Valor antiguo = item.getValor();
item.setValor(valor);
return antiguo;
}
}
}
listas[i].add(new Item<Clave, Valor>(clave, valor));
return null;
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 23
2. CLASES GENÉRICAS
public Valor get(Clave clave) {
int i = this.hash(clave);
Lista<Item<Clave, Valor>> lista = listas[i];
Iterador<Item<Clave, Valor>> iterador = lista.iterador();
while (iterador.hasNext()) {
Item<Clave, Valor> item = iterador.next();
if (clave.equals(item.getClave())) {
return item.getValor();
}
}
return null;
}

private int hash(Clave clave) {


int hash = clave.hashCode();
if (hash < 0) {
hash = Math.abs(hash + 1);
}
return hash % CAPACIDAD;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 24


2. CLASES GENÉRICAS
public static void main(String[] args) {
Map<String, Integer> map = new Map<String, Integer>();
map.put("Enero", new Integer(31));
map.put("Febrero", new Integer(28);
map.put("Marzo", new Integer(31));
map.put("Abril", new Integer(30));
map.put("Mayo", new Integer(31));

System.out.println("Enero = " + map.get("Enero"));


System.out.println("Febrero = " + map.get("Febrero"));
System.out.println("Marzo = " + map.get("Marzo"));
System.out.println("Abril = " + map.get("Abril"));
System.out.println("Mayo = " + map.get("Mayo"));
}

Enero = 31
Febrero = 28
Marzo = 31
Abril = 30
Mayo = 31

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 25


2. CLASES GENÉRICAS
LIMITACIONES DE LAS CLASES GENÉRICAS (I):
• No se pueden crear vectores de objetos de clases genéricas.
public class PilaAcotada<Elemento> {
protected Elemento[] elementos;

public PilaAcotada(int tamaño) {
elementos = new Elemento[tamaño]; // ERROR
elementos = (Elemento[]) new Object[tamaño]; // AVISO

}
}
PilaAcotada<Integer>[] pilas = new PilaAcotada<Integer>[10]; // ERROR
PilaAcotada<Integer>[] pilas = new PilaAcotada[10]; // AVISO

• No se pueden encarnar clases genéricas con tipos primitivos.


PilaAcotada<int> pilaEnteros; // ERROR

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 26


2. CLASES GENÉRICAS
LIMITACIONES DE LAS CLASES GENÉRICAS (II):
• No se pueden crear clases parametrizadas de excepciones.
public class MiExcepcion<Tipo> extends Exception {…} // ERROR

• No pueden aparecer genéricos en las cláusulas catch.


try {…} catch (E e) {…} // ERROR

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 27


2. CLASES GENÉRICAS
CLASES GENÉRICAS Y HERENCIA:
• Una clase genérica puede heredar de otra clase genérica.
public class PilaAcotada<Elemento> extends DispensadorAcotado<Elemento>

• Una clase genérica puede heredar de una clase no genérica.


public class PilaAcotada<Elemento> implements Serializable

• Una clase no genérica puede heredar de una clase genérica.


public class PilaEnteros extends PilaAcotada<Integer>

public final class Integer extends Number implements Comparable<Integer>

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 28


3. PARÁMETROS LIMITADOS
• En la declaración de un parámetro de tipo de una clase
parametrizada se puede especificar una restricción que debe
cumplir ese tipo; estos parámetros de tipo se conocen como
parámetros de tipo limitados (bounded).
SINTAXIS:
class <clase><<parámetro> extends <tipoBase>,…> {

}
• donde se especifica que el parámetro de tipo que se declara
<parámetro> debe ser el tipo <tipoBase> o cualquier tipo
derivado de él;
• el tipo base puede ser una clase o un interfaz;
• se pueden especificar más interfaces separándolos por &;
• el tipo base puede estar, a su vez, parametrizado.
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 29
3. PARÁMETROS LIMITADOS
• por ejemplo, la clase Intervalo puede parametrizarse, pero con la
restricción de que sus elementos puedan compararse entre sí;
Ej.
public class Intervalo<Elemento extends Comparable<Elemento>> {
private Elemento minimo;
private Elemento maximo;
protected Elemento getMinimo() {
return minimo;
}
protected Elemento getMaximo() {
return maximo;
}
public Intervalo(Elemento minimo, Elemento maximo) {
this.minimo = minimo;
this.maximo = maximo;
}
public Intervalo(Intervalo<Elemento> intervalo) {
this(intervalo.minimo, intervalo.maximo);
}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 30
3. PARÁMETROS LIMITADOS
public Intervalo<Elemento> copia() {
return new Intervalo<Elemento>(this);
}

public boolean incluye(Elemento elemento) {


return minimo.compareTo(elemento) <= 0 &&// LOS ELEMENTOS
maximo.compareTo(elemento) >= 0; // DEBEN SER COMPARABLES
}

public boolean incluye(Intervalo<Elemento> intervalo) {


return this.incluye(intervalo.minimo) &&
this.incluye(intervalo.maximo);
}

public boolean iguales(Intervalo<Elemento> intervalo) {


return minimo.equals(intervalo.minimo) &&
maximo.equals(intervalo.maximo);
}

public boolean distintos(Intervalo<Elemento> intervalo) {


return !this.iguales(intervalo);
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 31


3. PARÁMETROS LIMITADOS
public String toString() {
return "[" + minimo + ", " + maximo + "]";
}

public Intervalo<Elemento> interseccion(


Intervalo<Elemento> intervalo) {
if (this.incluye(intervalo)) {
return intervalo.copia();
} else if (intervalo.incluye(this)) {
return this.copia();
} else if (this.incluye(intervalo.minimo)) {
return new Intervalo<Elemento>(intervalo.minimo, this.maximo);
} else if (this.incluye(intervalo.maximo)) {
return new Intervalo<Elemento>(this.minimo, intervalo.maximo);
} else {
return null;
}
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 32


3. PARÁMETROS LIMITADOS
public static void main(String[] args) {
Intervalo<Integer> intervaloEnteros1 = new Intervalo<Integer>(
new Integer(1), new Integer(5));
Intervalo<Integer> intervaloEnteros2 = new Intervalo<Integer>(
new Integer(2), new Integer(3));
System.out.println("El intervalo " + intervaloEnteros1 +
(intervaloEnteros1.incluye(intervaloEnteros2) ? " SI" : " NO“) +
" incluye al intervalo " + intervaloEnteros2);

Intervalo<Double> intervaloReales1 = new Intervalo<Double>(


new Double(3.3), new Double(5.5));
Intervalo<Double> intervaloReales2 = new Intervalo<Double>(
new Double(4.4), new Double (6.6));
System.out.println("El intervalo " + intervaloReales1 +
(intervaloReales1.incluye(intervaloReales2) ? " SI" : " NO") +
" incluye al intervalo " + intervaloReales2);
}
}

El intervalo [1, 5] SI incluye al intervalo [2, 3]


El intervalo [3.3, 5.5] NO incluye al intervalo [4.4, 6.6]

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 33


3. PARÁMETROS LIMITADOS
Ej.
public class Fecha implements Comparable<Fecha> {

private Integer dia;


private Integer mes;
private Integer año;

public Fecha(Integer dia, Integer mes, Integer año) {


this.dia = dia;
this.mes = mes;
this.año = año;
}

public boolean iguales(Fecha fecha) {


return dia.equals(fecha.dia) &&
mes.equals(fecha.mes) &&
año.equals(fecha.año);
}

public boolean distintas(Fecha fecha) {


return !this.iguales(fecha);
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 34


3. PARÁMETROS LIMITADOS
public String toString() {
return dia + "/" + mes + "/" + año;
}

public int compareTo(Fecha fecha) {


if (año == fecha.año) {
if (mes == fecha.mes) {
return dia.compareTo(fecha.dia);
} else {
return mes.compareTo(fecha.mes);
}
} else {
return año.compareTo(fecha.año);
}
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 35


3. PARÁMETROS LIMITADOS
public static void main(String[] args) {
Fecha fecha11 = new Fecha(
new Integer(1), new Integer(1), new Integer(1982));
Fecha fecha12 = new Fecha(
new Integer(31), new Integer(12), new Integer(1982));
Intervalo<Fecha> intervaloFechas1 = new Intervalo<Fecha>(
fecha11, fecha12);

Fecha fecha21 = new Fecha(


new Integer(1), new Integer(4), new Integer(1982));
Fecha fecha22 = new Fecha(
new Integer(30), new Integer(4), new Integer(1982));
Intervalo<Fecha> intervaloFechas2 = new Intervalo<Fecha>(
fecha21, fecha22);
System.out.println("El intervalo " + intervaloFechas1 +
(intervaloFechas1.incluye(intervaloFechas2) ? " SI" : " NO") +
" incluye al intervalo " + intervaloFechas2);
}
}

El intervalo [1/1/1982, 31/12/1982] SI incluye


al intervalo [1/4/1982, 30/4/1982]
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 36
4. PARÁMETROS COMODINES
• Los parámetros de tipos comodines (wildcards) son parámetros
sin nombre que pueden usarse para declarar tipos parametrizados
de los atributos, argumentos, objetos locales y valores devueltos de
métodos de cualquier clase, parametrizada o no; y que representan
únicamente que se trata de un tipo cualquiera desconocido;
• se representan mediante el símbolo ?
• al ser anónimos no pueden usarse para referirse a él en el interior
de la clase o método donde se declaran;
• pueden limitarse como cualquier otro parámetro de tipo;
• su principal utilidad consiste en que relajan el sistema de tipos de
Java de forma que resulta más fácil asignar instancias de tipos
genéricos.
• Para ilustrar esta propiedad, supóngase el siguiente ejemplo:

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 37


4. PARÁMETROS COMODINES
Ej.
public class Lista<Elemento extends Number> {

public double suma(Lista<Number> lista) {
double suma = 0.0;
Iterador<Elemento> iterador = this.iterador();
while (iterador.hasNext()) {
Elemento elemento = iterador.next();
suma += elemento.doubleValue();
}
Iterador<Number> iteradorLista = lista.iterador();
while (iteradorLista.hasNext()) {
Number numero = iteradorLista.next();
suma += numero.doubleValue();
}
return suma;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 38


4. PARÁMETROS COMODINES

public static void main(String[] args) {
Integer i1 = new Integer(1);
Integer i2 = new Integer(2);
Integer i3 = new Integer(3);
Lista<Integer> listaEnteros = new Lista<Integer>();
listaEnteros.add(i1);
listaEnteros.add(i2);
listaEnteros.add(i3);

Double d1 = new Double(1.1);


Double d2 = new Double(2.2);
Double d3 = new Double(3.3);
Lista<Double> listaReales = new Lista<Double>();
listaReales.add(d1);
listaReales.add(d2);
listaReales.add(d3);
// ERROR DE COMPILACION
double suma = listaEnteros.suma(listaReales);
System.out.println("La suma de los elementos de " +
listaEnteros + " y " + listaReales + " es " + suma);
}
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 39


4. PARÁMETROS COMODINES
• El error de compilación se produce porque la clase Lista<Double>
no es una subclase de Lista<Number> aunque Double sea una
subclase de Number (¿por qué?).
• La razón es que si fuera así, entonces las siguientes sentencias:
Lista<Double> listaReales = new Lista<Double>();
Lista<Number> listaNumeros = listaReales; // ERROR
listaNumeros.add(new Integer(1));
Double doble = listaReales.get(0);

• harían que pudiéramos copiar una referencia a un entero en una


referencia a un doble, lo cual es incorrecto.
• Para resolver este error de compilación se debe usar un
parámetro de tipo comodín para declarar el tipo del argumento de
la función suma(), como se muestra a continuación:

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 40


4. PARÁMETROS COMODINES
Ej.
public class Lista<Elemento extends Number> {

public double suma(Lista<? extends Number> lista) {
double suma = 0.0;
Iterador<Elemento> iterador = this.iterador();
while (iterador.hasNext()) {
Elemento elemento = iterador.next();
suma += elemento.doubleValue();
}
Iterador<? extends Number> iteradorLista = lista.iterador();
while (iteradorLista.hasNext()) {
Number numero = iteradorLista.next();
suma += numero.doubleValue();
}
return suma;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 41


4. PARÁMETROS COMODINES
public static void main(String[] args) {
Integer i1 = new Integer(1);
Integer i2 = new Integer(2);
Integer i3 = new Integer(3);
Lista<Integer> listaEnteros = new Lista<Integer>();
listaEnteros.add(i1);
listaEnteros.add(i2);
listaEnteros.add(i3);
Double d1 = new Double(1.1);
Double d2 = new Double(2.2);
Double d3 = new Double(3.3);
Lista<Double> listaReales = new Lista<Double>();
listaReales.add(d1);
listaReales.add(d2);
listaReales.add(d3);
double suma = listaEnteros.suma(listaReales); // CORRECTO
System.out.println("La suma de los elementos de " +
listaEnteros + " y " + listaReales + " es " + suma);
}
}

La suma de los elementos de {1; 2; 3} y {1.1; 2.2; 3.3} es 12.600000000000001


Tema 7. PROGRAMACIÓN PARAMETRIZADA - 42
4. PARÁMETROS COMODINES
• El error de compilación no se produce porque el uso del
parámetro comodín relaja el sistema de tipos, de manera que las
siguientes sentencias son correctas:
Lista<Double> listaReales = new Lista<Double>();
Lista<? extends Number> listaNumeros = listaReales; // CORRECTO

• Sin embargo, usar el parámetro comodín impone que con la


referencia no se puedan usar métodos de la clase parametrizada
que pudieran producir una incompatibilidad de tipos:
listaNumeros.add(new Double(3)); // ERROR
Double x = listaNumeros.get(0); // ERROR

• pero sí se pueden usar métodos que no puedan producir


incompatibilidad de tipos:
Number x = listaNumeros.get(0); // CORRECTO
String cadena = listaNumeros.toString(); // CORRECTO
listaNumeros.clear(); // CORRECTO

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 43


4. PARÁMETROS COMODINES
Ej.
public class Lista<Elemento extends Number> {

public void addAll(Lista<? extends Elemento> lista) {
Iterador<? extends Elemento> iteradorLista = lista.iterador();
while (iteradorLista.hasNext()) {
Elemento elemento = iteradorLista.next();
this.add(elemento);
}
}

public static void main(String[] args) {

Lista<Number> listaNumeros = new Lista<Number>();
listaNumeros.addAll(listaEnteros);
listaNumeros.addAll(listaReales);
System.out.println("La lista resultado de unir " +
listaEnteros + " y " + listaReales + " es " +
listaNumeros);

}

La lista resultado de unir {1; 2; 3} y {1.1; 2.2; 3.3}


es {1; 2; 3; 1.1; 2.2; 3.3}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 44
5. MÉTODOS GENÉRICOS
• Los métodos también se pueden parametrizar, tanto si están en
una clase parametrizada como si no lo están.
• Para parametrizar un método se declaran los parámetros de tipo
antes de la declaración del tipo del valor devuelto por el método.
SINTAXIS:
<acceso> <<parámetro1>,…,<parámetroN>>
<tipoDevuelto> <nombreMétodo>(<argumentos>) {

}

• Los parámetros de tipo pueden usarse dentro del método


parametrizado para declarar el tipo del valor devuelto por el
método, de sus argumentos y de sus objetos locales.
• Estos parámetros de tipo (formales) se especifican posteriormente
con un tipo concreto (actual) al invocar el método parametrizado, lo
que produce la encarnación del método. Tema 7. PROGRAMACIÓN PARAMETRIZADA - 45
5. MÉTODOS GENÉRICOS
Ej.
public class Lista<Elemento extends Number> {

public <Tipo extends Number> Lista<Tipo> mayores(Lista<Tipo> lista) {
Lista<Tipo> mayores = new Lista<Tipo>();
Iterador<Elemento> iterador = this.iterador();
Iterador<Tipo> iteradorLista = lista.iterador();
while (iterador.hasNext() && iteradorLista.hasNext()) {
Elemento elemento = iterador.next();
Tipo valor = iteradorLista.next();
if (valor.doubleValue() > elemento.doubleValue()) {
mayores.add(valor);
}
}
return mayores;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 46


5. MÉTODOS GENÉRICOS
public static void main(String[] args) {
Integer i1 = new Integer(1);
Integer i2 = new Integer(2);
Integer i3 = new Integer(3);
Lista<Integer> listaEnteros = new Lista<Integer>();
listaEnteros.add(i1);
listaEnteros.add(i2);
listaEnteros.add(i3);
Double d1 = new Double(0.5);
Double d2 = new Double(2.7);
Double d3 = new Double(3.1);
Lista<Double> listaReales = new Lista<Double>();
listaReales.add(d1);
listaReales.add(d2);
listaReales.add(d3);
Lista<Double> mayoresReales = listaEnteros.mayores(listaReales);
System.out.println("Los elementos de " + listaReales +
" mayores que " + listaEnteros + " son " + mayoresReales);
Lista<Integer> mayoresEnteros = listaReales.mayores(listaEnteros);
System.out.println("Los elementos de " + listaEnteros +
" mayores que " + listaReales + " son " + mayoresEnteros);
}
}

Los elementos de {0.5; 2.7; 3.1} mayores que {1; 2; 3} son {2.7; 3.1}
Los elementos de {1; 2; 3} mayores que {0.5; 2.7; 3.1} son {1}
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 47
ÍNDICE
CASO DE ESTUDIO:
Colecciones
1. Introducción
2. Listas
3. Colas
4. Conjuntos
5. Mapas

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 48


1. INTRODUCCIÓN
Colecciones: Java proporciona en el paquete java.util un conjunto
de clases para representar y manejar estructuras de datos.
• Antes de la aparición de la plataforma Java 2, sólo se disponía de
un conjunto muy limitado de clases para las estructuras de datos
más comunes: Vector, Stack, Hashtable, y el interfaz Enumeration
para recorrer los elementos de estas clases.
• Java 2 incorpora un framework más completo inspirado en la
librería STL de C++, pero manteniendo compatibles las clases
heredadas de las versiones anteriores.
• Esta biblioteca de clases separa los interfaces de sus
implementaciones, lo que proporciona mayor abstracción al usar la
biblioteca, y facilita la extensibilidad de la misma.
• A partir de la JDK 1.5 las clases de la biblioteca son clases
parametrizadas.
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 49
1. INTRODUCCIÓN

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 50


1. INTRODUCCIÓN

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 51


1. INTRODUCCIÓN
Interfaz Collection<E>: Es la raíz de la jerarquía de las clases de
colecciones, y proporciona los métodos comunes a todas ellas:
int size()
boolean isEmpty()
boolean contains(Object o)
boolean containsAll(Collection<?> c)
Iterator<E> iterator()
Object[] toArray()
<T> T[] toArray(T[] a)
boolean add(E e)
boolean remove(Object o)
boolean addAll(Collection<? extends E> c)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)
void clear()
boolean equals(Object o)
int hashCode()
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 52
1. INTRODUCCIÓN
Interfaz Iterator<E>: Permite recorrer los elementos de las clases
de colecciones:
boolean hasNext()
E next()
void remove()

• donde el método remove() debe llamarse sólo después de next(),


y elimina de la colección el último elemento devuelto por éste;
• no debe modificarse una colección mientras un iterador la recorre
de ninguna otra manera que invocando remove() sobre ese
iterador, porque, en otro caso, el comportamiento del iterador no
está definido (la implementación actual produce una excepción
ConcurrentModificationException);

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 53


2. LISTAS
Interfaz List<E>: Representa una secuencia de elementos que
ocupan una cierta posición en la colección, en la que puede haber
elementos repetidos.
E get(int index)
E set(int index, E element)
void add(int index, E element)
E remove(int index)
int indexOf(Object o)
int lastIndexOf(Object o)
ListIterator<E> listIterator()
ListIterator<E> listIterator(int index)
List<E> subList(int fromIndex, int toIndex)
boolean addAll(int index, Collection<? extends E> c)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 54


2. LISTAS
Interfaz ListIterator<E>: Recorre los elementos de una lista:
boolean hasPrevious()
E previous()
int nextIndex()
int previousIndex()
void add(E e)
void set(E e)
• donde el método remove() debe llamarse sólo después de next() o
previous(), y elimina de la colección el último elemento devuelto
por éstos;
• donde add() inserta justo antes del elemento que se obtendría
con next() y justo después del elemento que se obtendría con
previous();
• set() reemplaza el último elemento devuelto por next() o
previous(), y sólo puede invocarse si después de estas operaciones
no se ha invocado add() o set(); Tema 7. PROGRAMACIÓN PARAMETRIZADA - 55
2. LISTAS
• Las clases que implementan el interfaz List<E> son:
Clase ArrayList<E>: que proporciona una implementación
basada en vectores de elementos que autoajustan su tamaño
según se añaden elementos;
public ArrayList()
public ArrayList(int initialCapacity)
public ArrayList(Collection<? extends E> c)
public void trimToSize()
public void ensureCapacity(int minCapacity)

Clase LinkedList<E>: que utiliza listas doblemente enlazadas;


además implementa el interfaz Deque<E>, por lo que puede
usarse para tratar con colas (se verá más adelante);
public LinkedList()
public LinkedList(Collection<? extends E> c)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 56


2. LISTAS
Clase Vector<E>: también usa vectores autoajustables, y se
mantiene por razones de compatibilidad con código heredado;
además está sincronizada para evitar accesos concurrentes, lo
que conlleva un cierto sobrecoste adicional;
public Vector()
public Vector(int initialCapacity)
public Vector(int initialCapacity, int capacityIncrement)
public Vector(Collection<? extends E> c)
public void copyInto(Object[] anArray)
public void trimToSize()
public void ensureCapacity(int minCapacity)
public void setSize(int newSize)
public int capacity()
public Enumeration<E> elements()
public int indexOf(Object o, int index)
public int lastIndexOf(Object o, int index)
public E elementAt(int index)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 57
2. LISTAS
public E firstElement()
public E lastElement()
public void setElementAt(E obj, int index)
public void removeElementAt(int index)
public void insertElementAt(E obj, int index)
public void addElement(E obj)
public boolean removeElement(Object obj)
public void removeAllElements()

Stack<E>: Representa una pila LIFO.


public Stack()
public E push(E item)
public E pop()
public E peek()
public boolean empty()
public int search(Object o)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 58


3. COLAS
Interfaz Queue<E>: Las colas ordenan sus elementos según un
orden determinado (normalmente FIFO, aunque no
necesariamente):
boolean offer(E e)
E remove()
E poll()
E element()
E peek()

Excepción No excepción

Inserción add() offer()

Extracción remove() poll()

Consulta element() peek()

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 59


3. COLAS
• La única clase que implementa el interfaz Queue<E> es:
Clase PriorityQueue<E>: proporciona una implementación
basada en prioridades que se establecen por el orden natural
de sus elementos (según el interfaz Comparable) o por un
comparador de elementos que se suministra a la cola en su
construcción. Todas las claves deben implementar el interfaz
Comparable (o ser aceptadas por su Comparator).
public PriorityQueue()
public PriorityQueue(int initialCapacity)
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator)
public PriorityQueue(Collection<? extends E> c)
public PriorityQueue(PriorityQueue<? extends E> c)
public PriorityQueue(SortedSet<? extends E> c)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 60


3. COLAS
Interfaz Deque<E>: Son colas que permiten la inserción y
extracción de elementos en ambos extremos (double ended queue).
void addFirst(E e)
void addLast(E e)
boolean offerFirst(E e)
boolean offerLast(E e)
E removeFirst()
E removeLast()
E pollFirst()
E pollLast()
E getFirst()
E getLast()
E peekFirst()
E peekLast()
boolean removeFirstOccurrence(Object o)
boolean removeLastOccurrence(Object o)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 61


3. COLAS
void push(E e)
E pop()
Iterator<E> descendingIterator()

• Las clases que implementan el interfaz Deque<E> son:


Clase LinkedList<E>: Implementación mediante listas
doblemente enlazadas.
public LinkedList()
public LinkedList(Collection<? extends E> c)

Clase ArrayDeque<E>: Implementación mediante vectores


autoajustables.
public ArrayDeque()
public ArrayDeque(Collection<? extends E> c)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 62


4. CONJUNTOS
Interfaz Set<E>: Representa una colección de elementos no
repetidos. No añade ningún método nuevo a Collection<E>, sólo
estipula ciertas restricciones en sus métodos;
• Las clases que implementan este interfaz son:
Clase EnumSet<E extends Enum<E>>: Los elementos del
conjunto deben ser valores de enumerados. Proporcionan una
representación muy compacta y eficiente. Los elementos se
recorren según su orden natural. La clase es abstracta y sólo
tiene métodos genéricos estáticos para crear los conjuntos.
public static <E extends Enum<E>> EnumSet<E>
noneOf(Class<E> elementType)
public static <E extends Enum<E>> EnumSet<E>
allOf(Class<E> elementType)
public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s)
public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 63
4. CONJUNTOS
public static <E extends Enum<E>> EnumSet<E>
complementOf(EnumSet<E> s)
public static <E extends Enum<E>> EnumSet<E> of(E e)
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2)
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3)
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4)
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest)
public static <E extends Enum<E>> EnumSet<E> range(E from, E to)
public EnumSet<E> clone()
Clase HashSet<E>: Implementación mediante una tabla hash
(realmente un HashMap). No garantiza ningún orden al iterar
sobre el conjunto.
public HashSet()
public HashSet(int initialCapacity)
public HashSet(int initialCapacity, float loadFactor)
public HashSet(Collection<? extends E> c)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 64
4. CONJUNTOS
Clase LinkedHashSet<E>: Implementación mediante tabla hash y
listas enlazadas (mediante LinkedHashMap), en la que los
elementos se recorren en el mismo orden en el que se
insertaron.
public LinkedHashSet()
public LinkedHashSet(int initialCapacity)
public LinkedHashSet(int initialCapacity, float loadFactor)
public LinkedHashSet(Collection<? extends E> c)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 65


4. CONJUNTOS
Interfaz SortedSet<E>: Representa un conjunto que establece un
orden total sobre sus elementos. Los elementos se ordenan por su
orden natural (según el interfaz Comparable) o por un comparador
de elementos que se suministra al conjunto en su construcción.
Todas las claves deben implementar el interfaz Comparable (o ser
aceptadas por su Comparator).
Comparator<? super E> comparator()
SortedSet<E> subSet(E fromElement, E toElement)
SortedSet<E> headSet(E toElement)
SortedSet<E> tailSet(E fromElement)
E first()
E last()

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 66


4. CONJUNTOS
Interfaz NavigableSet<E>: Extiende SortedSet<E> para buscar un
elemento menor, menor o igual, mayor o igual, y mayor que un
cierto elemento dado, más otros métodos de búsqueda.
E lower(E e)
E floor(E e)
E ceiling(E e)
E higher(E e)
E pollFirst()
E pollLast()
NavigableSet<E> descendingSet()
Iterator<E> descendingIterator()
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive)
NavigableSet<E> headSet(E toElement, boolean inclusive)
NavigableSet<E> tailSet(E fromElement, boolean inclusive)
SortedSet<E> subSet(E fromElement, E toElement)
SortedSet<E> headSet(E toElement)
SortedSet<E> tailSet(E fromElement) Tema 7. PROGRAMACIÓN PARAMETRIZADA - 67
4. CONJUNTOS
• La única clase que implementa el interfaz NavigableSet<E> es:
Clase TreeSet<E>: Implementación mediante TreeMap, en la
que los elementos se recorren según su orden natural.
public TreeSet()
public TreeSet(Comparator<? super E> comparator)
public TreeSet(Collection<? extends E> c)
public TreeSet(SortedSet<E> s)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 68


5. MAPAS
Interfaz Map<K,V>: Un mapa representa una colección de
elementos formados por una clave y un valor. En un mapa no puede
haber elementos con claves repetidas, cada clave puede tener un
valor como máximo.
boolean containsKey(Object key)
boolean containsValue(Object value)
V get(Object key)
V put(K key, V value)
V remove(Object key)
void putAll(Map<? extends K,? extends V> m)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 69


5. MAPAS
• Las clases que implementan este interfaz son:
Clase EnumMap<K extends Enum<K>,V>: Implementación para
usarse con claves de tipo enumerados. Las claves deben ser
valores de enumerados. Proporcionan una representación muy
compacta y eficiente basada en vectores. Los elementos se
recorren según su orden natural.
public EnumMap(Class<K> keyType)
public EnumMap(EnumMap<K,? extends V> m)
public EnumMap(Map<K,? extends V> m)
Clase HashMap<K,V>: Implementación mediante una tabla
hash. No garantiza ningún orden al iterar sobre el mapa.
public HashMap()
public HashMap(int initialCapacity)
public HashMap(int initialCapacity, float loadFactor)
public HashMap(Map<? extends K,? extends V> m)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 70
5. MAPAS
Clase LinkedHashMap<K,V>: Implementación mediante una
tabla hash y listas doblemente enlazadas. Los elementos se
recorren en el orden de inserción de sus claves.
public LinkedHashMap()
public LinkedHashMap(int initialCapacity)
public LinkedHashMap(int initialCapacity, float loadFactor)
public LinkedHashMap(Map<? extends K,? extends V> m)
public LinkedHashMap(int initialCapacity, float loadFactor,
boolean accessOrder)
Clase WeakHashMap<K,V>: Implementación mediante una
tabla hash y claves débiles. Los elementos cuyas claves dejan de
ser referenciadas se destruyen automáticamente.
public WeakHashMap()
public WeakHashMap(int initialCapacity)
public WeakHashMap(int initialCapacity, float loadFactor)
public WeakHashMap(Map<? extends K,? extends V> m)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 71
5. MAPAS
Clase IdentityHashMap<K,V>: Implementación mediante una
tabla hash y con comparación de claves y valores mediante ==
en lugar de equals.
public IdentityHashMap()
public IdentityHashMap(int expectedMaxSize)
public IdentityHashMap(Map<? extends K,? extends V> m)

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 72


5. MAPAS
Interfaz SortedMap<K,V>: Un mapa que proporciona un orden
total sobre sus claves. El mapa se ordena según el orden natural de
sus claves, o mediante un Comparator que se suministra al crear el
mapa. Este orden se sigue al iterar sobre las colecciones que
devuelve el mapa. Todas las claves deben implementar el interfaz
Comparable (o ser aceptadas por su Comparator).
Comparator<? super K> comparator()
SortedMap<K,V> subMap(K fromKey, K toKey)
SortedMap<K,V> headMap(K toKey)
SortedMap<K,V> tailMap(K fromKey)
K firstKey()
K lastKey()
Set<K> keySet()

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 73


5. MAPAS
Interfaz NavigableMap<K,V> (I): Extiende SortedMap<E> para
buscar un elemento menor, menor o igual, mayor o igual, y mayor
que un cierto elemento dado, más otros métodos de búsqueda.
Map.Entry<K,V> lowerEntry(K key)
K lowerKey(K key)
Map.Entry<K,V> floorEntry(K key)
K floorKey(K key)
Map.Entry<K,V> ceilingEntry(K key)
K ceilingKey(K key)
Map.Entry<K,V> higherEntry(K key)
K higherKey(K key)
Map.Entry<K,V> firstEntry()
Map.Entry<K,V> lastEntry()
Map.Entry<K,V> pollFirstEntry()
Map.Entry<K,V> pollLastEntry()
NavigableMap<K,V> descendingMap()

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 74


5. MAPAS
Interfaz NavigableMap<K,V> (II):
NavigableSet<K> navigableKeySet()
NavigableSet<K> descendingKeySet()
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
K toKey, boolean toInclusive)
NavigableMap<K,V> headMap(K toKey, boolean inclusive)
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)

• La única clase que implementa el interfaz NavigableMap<K,V> es:


Clase TreeMap<K,V>: Implementación mediante un árbol, en la
que los elementos se recorren según su orden natural (o en el
orden que proporciona su Comparator).
public TreeMap()
public TreeMap(Comparator<? super K> comparator)
public TreeMap(Map<? extends K,? extends V> m)
public TreeMap(SortedMap<K,? extends V> m)
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 75
5. MAPAS
Ej.
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

public class MultiMap<Clave ,Valor> {

private Map<Clave, Collection<Valor>> map =


new HashMap<Clave, Collection<Valor>>();

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 76


5. MAPAS
public boolean add(Clave clave, Valor valor) {
boolean add = false;
Collection<Valor> coleccion = this.get(clave);
if (coleccion == null) {
coleccion = new LinkedList<Valor>();
coleccion.add(valor);
map.put(clave, coleccion);
add = true;
} else {
Valor actual = null;
Iterator<Valor> iterador = coleccion.iterator();
while (iterador.hasNext() && !valor.equals(actual)) {
actual = iterador.next();
}
if (!valor.equals(actual)) {
coleccion.add(valor);
map.put(clave, coleccion);
add = true;
}
}
return add;
}

Tema 7. PROGRAMACIÓN PARAMETRIZADA - 77
5. MAPAS
public Collection<Valor> get(Clave clave) {
return map.get(clave);
}
public static void main(String[] args) {
MultiMap<String, Integer> multimap =
new MultiMap<String, Integer>();
multimap.add("Enero", new Integer(1));
multimap.add("Enero", new Integer(2));
multimap.add("Enero", new Integer(1));
multimap.add("Febrero", new Integer(1));
multimap.add("Febrero", new Integer(1));
multimap.add("Marzo", new Integer(1));
multimap.add("Marzo", new Integer(3));
multimap.add("Marzo", new Integer(2));
System.out.println("Enero = " + multimap.get("Enero"));
System.out.println("Febrero = " + multimap.get("Febrero"));
System.out.println("Marzo = " + multimap.get("Marzo"));
System.out.println("Abril = " + multimap.get("Abril"));
}

Enero = [1, 2]
Febrero = [1]
Marzo = [1, 3, 2]
Abril = null
Tema 7. PROGRAMACIÓN PARAMETRIZADA - 78

También podría gustarte