5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! •...

31
Introducción a la Programación Tema 5. Tratamientos Secuenciales 1. Introducción ......................................................................................................................... 1 2. Esquemas Iterativos ............................................................................................................. 5 2.1 Suma ............................................................................................................................. 5 2.2 Producto ....................................................................................................................... 7 2.3 Contador ....................................................................................................................... 8 2.4 Selecciona Lista............................................................................................................. 8 2.5 Selecciona Conjunto ..................................................................................................... 9 2.6 Selecciona Array ........................................................................................................... 9 2.7 Ejecuta Para Todo....................................................................................................... 10 2.8 Para Todo.................................................................................................................... 10 2.9 Existe ........................................................................................................................... 11 2.10 Busca Primero ............................................................................................................. 12 2.11 Posición del Primero ................................................................................................... 13 2.12 Máximo: ...................................................................................................................... 14 2.13 Mínimo: ...................................................................................................................... 17 2.14 Iteración Genérica ...................................................................................................... 19 2.15 Algoritmos para grupos consecutivos de elementos: ................................................ 22 3. Ejemplos y Metodología de trabajo................................................................................... 23 4. Conceptos aprendidos ........................................................................................................ 29 5. Ejercicios Propuestos ......................................................................................................... 29 1. Introducción Al tratar con agregados de datos (listas, conjuntos, arrays, cadenas de caracteres, secuencias de valores y en general todos los tipos que implementen la interfaz Iterable) es muy común buscar información sobre cantidades agregadas: máximos o mínimos, posiciones de elementos en el agregado, etc. Estos tratamientos se repiten continuamente. Nuestro objetivo en este tema es estudiar estos tratamientos sobre agregados de datos, hacer un catálogo lo más extenso posible de los mismos y, a ser posible, implementarlos en métodos que puedan ser reutilizados. Dado un agregado de objetos podemos plantearnos preguntas del tipo:

Transcript of 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! •...

Page 1: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

Introducción  a  la  Programación    Tema  5.  Tratamientos  Secuenciales    1.   Introducción  .........................................................................................................................  1  

2.   Esquemas  Iterativos  .............................................................................................................  5  

2.1   Suma  .............................................................................................................................  5  

2.2   Producto  .......................................................................................................................  7  

2.3   Contador  .......................................................................................................................  8  

2.4   Selecciona  Lista  .............................................................................................................  8  

2.5   Selecciona  Conjunto  .....................................................................................................  9  

2.6   Selecciona  Array  ...........................................................................................................  9  

2.7   Ejecuta  Para  Todo  .......................................................................................................  10  

2.8   Para  Todo  ....................................................................................................................  10  

2.9   Existe  ...........................................................................................................................  11  

2.10   Busca  Primero  .............................................................................................................  12  

2.11   Posición  del  Primero  ...................................................................................................  13  

2.12   Máximo:  ......................................................................................................................  14  

2.13   Mínimo:  ......................................................................................................................  17  

2.14   Iteración  Genérica  ......................................................................................................  19  

2.15   Algoritmos  para  grupos  consecutivos  de  elementos:  ................................................  22  

3.   Ejemplos  y  Metodología  de  trabajo  ...................................................................................  23  

4.   Conceptos  aprendidos  ........................................................................................................  29  

5.   Ejercicios  Propuestos  .........................................................................................................  29  

     1. Introducción  

 Al   tratar  con  agregados  de  datos  (listas,  conjuntos,  arrays,  cadenas  de  caracteres,  secuencias  de  valores  y  en  general   todos   los   tipos  que   implementen   la   interfaz   Iterable)  es  muy  común  buscar  información  sobre  cantidades  agregadas:  máximos  o  mínimos,  posiciones  de  elementos  en   el   agregado,   etc.   Estos   tratamientos   se   repiten   continuamente.  Nuestro   objetivo   en   este  tema   es   estudiar   estos   tratamientos   sobre   agregados   de   datos,   hacer   un   catálogo   lo   más  extenso  posible  de   los  mismos  y,   a   ser  posible,   implementarlos  en  métodos  que  puedan   ser  reutilizados.    

Dado  un  agregado  de  objetos  podemos  plantearnos  preguntas  del  tipo:  

Page 2: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 2   Introducción  a  la  Programación  

 • ¿cuánto  vale  la  suma  de  una  expresión  de  los  objetos  del  agregado?    • ¿y  el  producto  de  los  que  verifican  una  propiedad?  • ¿existe  algún  objeto  que  verifique  una  determinada  condición?  • ¿cuáles  son  los  objetos  que  cumplen  una  determinada  propiedad?  • ¿cuál  es  el  valor  más  grande  de  los  que  cumplen  una  condición?  • ¿según  un  orden  dado  cuál  es  mayor  elemento  para  una  condición?  • actualiza  todos  los  objetos  que  cumplen  una  condición  • almacena  en  una  lista  los  objetos  que  cumplan  una  condición  • etc.    

Cada  una  de  esas  preguntas  y  otras  similares  pueden  ser  respondidas  con  métodos  que  tienen  una  estructura  común.    Ejemplo:   ¿Cómo   se   calcula   la   suma  de   los   cuadrados  de   los   números  enteros   contenidos   en  una  lista  de  Enteros?    Como   el   agregado   es   una   lista   usamos   un   for   extendido   para   recorrerla.   El   código   lo  concretamos  en  un  método  que   tomando  una   lista   como  parámetro  y  devuelve  el   resultado  esperado.    

public static Integer sumaCuadrados(List<Integer> v){ Integer suma=0; for (Integer e: v){

suma = suma + e*e; } return suma; }

 Igualmente  podemos  preguntarnos  por  la  suma  de  los  cuadrados  de  todos  los  enteros  que  van  desde  un  entero  dado,  a,  hasta  otro  b  (mayor  que  a)  en  pasos  de  c  (positivos).  Por  ejemplo  la  secuencia  10,  12,  14,  16,  18,  20  sería  especificada  por  a=10,  b=20,  c=2.    Para  generar  la  secuencia  usamos  un  for  clásico.  El  método  resultante  es:    

public static Integer sumaCuadradosIntervalo(Integer a, Integer b, Integer c){ if(!(b>a && c>0)) throw new IllegalArgumentException(); Integer suma=0; for (Integer e=a; e<=b; e=e+c){

suma = suma + e*e; } return suma; }

 El   método   anterior   dispara   una   excepción   si   los   parámetros   recibidos   no   cumplen   lo  especificado.   Salvando   la   comprobación   de   la   idoneidad   de   los   parámetros   ambos  métodos  tienen,  como  vemos,  la  misma  estructura.    

Page 3: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  3  5.  Tratamientos  secuenciales  

 Veamos  ahora  un  problema  más  general:   sumar   los   cuadrados  de   los  enteros   contenidos  en  una  lista  que  son  múltiplos  de  3.    

 public static Integer sumaCuadradosMultiplos3(List<Integer> v){ Integer suma=0; for(Integer e: v){ if(Enteros.esMultiplo(e,3)){

suma = suma + e*e; } } return suma; }

 O  en  la  secuencia  definida  por  a,  b,  c.  Es  decir  los  enteros  desde  a  hasta  b  con  incrementos  de  c.    

public static Integer sumaCuadradosIntervaloMultiplos3(Integer a, Integer b, Integer c){ if(!(b>a && c>0)) throw new IllegalArgumentException(); Integer suma=0; for(Integer e= a; e<=b; e=e+c){ if(Enteros.esMultiplo(e,3)){

suma = suma + e*e; } } return suma; }

   En   estos   métodos   aparece   una   estructura   que   se   repetirá.   Esta   estructura   tiene   varios  elementos  a  destacar:  acumulador,  filtro,  expresión.    

• Acumulador:  es  una  variable  que  acumula  el  resultado  calculado  hasta  ese  momento.  Se   inicializa  al  valor  adecuado  para   la  secuencia  o  el  agregado  vacío  y  es  del   tipo  del  resultado  que  queramos  calcular.  En  este  caso   la  variable  es  suma  que  se   inicializa  a  cero  y  es  de  tipo  Integer  como  el  resultado.  

• Filtro:   es   una   expresión   lógica   sin   efectos   laterales   que   nos   sirve   para   escoger   los  elementos   del   agregado   sobre   los   que   vamos   a   hacer   el   cálculo.   En   este   caso   es   la  expresión  Enteros.esMultiplo(e,3).    

• Expresión:  es  una  expresión  que  a  partir  de  cada  objeto  del  agregado  calcula  el  valor  que  se  va  acumulando.  En  este  caso  la  expresión  es  e*e.  

• Fuente   de   Datos:   Es   el   agregado   a   partir   del   cual   queremos   calcular   el   valor  acumulado.  En   los   tratamientos   secuenciales  distinguiremos   tres   tipos  de   fuentes  de  datos:  

Page 4: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 4   Introducción  a  la  Programación  

o Agregados  que  ofrecen  el  interface  Iterable<T>.  Son  los  más  generales  y,  como  veremos  en  los  próximos  capítulos,   los  demás  tipos  de  agregados  pueden  ser  convertidos  a  éste.  Para  recorrerlos  usamos  un  for  extendido.  

o Arrays.   Es  decir   agregados  de   tipo  T[].   Para   recorrerlos  podemos  usar  un   for  extendido  o  un  for  clásico.  

o Secuencias   de   números.   Pueden   ser   generadas   mediante   un   for   clásico.  Veremos  ejemplos  en  adelante.  

 Junto   a   los   conceptos   anteriores   podemos   introducir   brevemente   otros   dos   importantes:   el  invariante  y  la  función  de  cota:    

• Invariante:   es   una   expresión   lógica   que   se   mantiene   verdadera   en   cada   una   de   las  iteraciones.   En   nuestro   caso   el   invariante   es:   la   variable   acumulador   contiene   el  resultado  de  acumular  los  valores  de  la  Expresión  calculados  sobre  aquellos  elementos  recorridos  hasta  ese  momento  que  cumpliendo  la  condición  de  Filtro.    

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.    Los  conceptos  anteriores  son  importantes  para  un  buen  diseño  de  los  métodos.  La  Función  de  Cota   de   disminuir   en   cada   iteración   y   tener   un   valor   mayor   o   igual   a   cero.   Si   cumple   etas  propiedades  tenemos  garantía  que  el  método  termina.  El  invariante  nos  indica  una  propiedad  que  se  conserva.  En  el  ejemplo  anterior  la  variable  suma  es,  en  cada  momento,  igual  a  la  suma  de  los  elementos  recorridos  del  iterable  que  cumplen  el  filtro.  Esta  propiedad  es  verdadera  al  terminar  la  iteración.    Como  el  Invariante  se  va  manteniendo  verdadero  y  la  Función  de  Cota  es  adecuada  podemos  concluir  que  los  métodos  están  bien  diseñados.    En  los  diseños  anteriores  hemos  asumido  que  el  origen  de  datos  no  contiene  el  valor  null.  Esto  es  cierto  en  la  secuencia  de  enteros  pero  puede  no  serlo  cuando  el  origen  de  datos  es  una  lista  o   un   array.   Cuando   el   origen   de   datos   puede   contener   null,   o   simplemente   no   tenemos  garantías  de  que  no  aparecerá  un  valor  null,  entonces  hay  que  reforzar  la  expresión  que  hace  de  filtro  para  que  el  esquema  funcione  correctamente  e  impedir  que  se  disparen  excepciones.    

public static Integer sumaCuadradosMultiplos3(List<Integer> v){ Integer suma=0; for(Integer e: v){ if(e!=null && Enteros.esMultiplo(e,3)){

suma = suma + e*e; } } return suma; }

 Por  robustez  es  muy  importante  realizar  esta  comprobación.      

Page 5: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  5  5.  Tratamientos  secuenciales  

2. Esquemas  Iterativos    Dependiendo   de   lo   que   queramos   acumular.   A   estas   estructuras   de   uso   muy   frecuente   las  denominaremos   Esquemas   Iterativos.   Todos   ellos   comparten   los   elementos   explicados  anteriormente:  fuente  de  datos,  acumulador,   filtro  y  expresión.  Para  dar   los  detalles  de  cada  uno  de  ellos  tenemos  que  indicar:    

• Su  objetivo.  Por  ejemplo  sumar  los  valores  del  agregado  si  estos  son  numéricos.  • Tipo  del  acumulador:  en  el  caso  de  la  suma  es  Double,  Integer  u  otro  tipo  numérico.  • Valor  Inicial:  valor  del  acumulador  si  el  agregado  está  vacío.  En  el  caso  de  la  suma  es  

cero.  • Expresión   acumuladora:   Es   la   forma   concreta   en   la   que   se   actualiza   el   valor   del  

acumulador  en  cada  iteración.  De  estas  expresiones  acumuladoras  tenemos  dos  tipos:  o El  acumulador,  un  operador  binario  y  una  expresión.  En  el  caso  de  la  suma  es  

el  operador  binario  +.  o Cuando   el   acumulador   es   de   tipo   objeto   la   expresión   acumuladora   se  

compone   de   la   llamada   a   un   método   del   acumulador   pasándole   como  parámetro  la  expresión  a  acumular.  

 Los  esquemas   iterativos  podemos  diseñarlos  todos  como  una  misma  estructura  general  pero  en  algunos   casos  es   conveniente   tener  esquemas  alternativos.   Esto  ocurre   cuando   se  puede  obtener  el  resultado  sin  necesidad  de  recorrer  todos  los  elementos  del  agregado  o  cuando  el  esquema  puede  simplificarse  haciendo  un  tratamiento  específico  del  primer  elemento.      Veremos   en   primer   lugar   los   métodos   similares   a   la   suma.   Todos   ellos   tienen   la   misma  estructura  que  la  vista  para  la  suma.  Para  cada  método  mostraremos  su  objetivo,  su  código  y  las  características  anteriores.    2.1 Suma  

• Objetivo:   Suma   de   los   valores   calculados   por   la   expresión   sobre   los   elementos   que  cumplen  el  filtro.  

• Tipo  del  acumulador:  Double,  Integer  u  otro  tipo  numérico.    • Valor  Inicial:  Cero.  • Expresión  acumuladora:  El  acumulador  más  la  expresión.  • Operador  binario:  +  • Invariante:  la  variable  suma  contiene  el  resultado  de  sumar  los  valores  de  la  Expresión  

calculados   sobre   aquellos   elementos   recorridos   hasta   ese  momento   que   cumplen   la  condición  de  Filtro.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:    

Iterable<T> agregado = ...; Double suma = 0.0;

for (T e : agregado) {

if (Filtro) {

Page 6: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 6   Introducción  a  la  Programación  

suma = suma + Expresion; } }

 

En  el  código  anterior  hemos  asumido  que  el  valor  que  valor  a  sumar  es  de  tipo  Double  y  que  la  fuente  de  datos  es  de  tipo  Iterable<T>.  Filtro  es  una  expresión  sobre  la  variable  e  que  devuelve  boolean.   Esta   expresión   que   hace   el   pael   de   Filtro   debe   tener   en   cuenta   en   su   caso   la  posibilidad   de   que   algún   valor   sea   null   como   se   ha   explicado  más   arriba.   Expresion   es   una  expresión  sobre  la  variable  e  que  devuelve  Double.  El  esquema  es  similar  si  el  tipo  del  valor  a  acumular  es  cualquier  tipo  numérico.  Por  ejemplo  si  el  valor  a  acumular  es  Integer  este  será  el  tipo  de  la  variable  suma,  que  se  inicializará  a  1,  y  Expresion  devolverá  un  valor  de  tipo  Integer.  

Si  el  filtro  fuera  siempre  true,  es  decir  no  hay  filtro  el  esquema  se  simplifica  a:  

 

Iterable<T> agregado = ...; Double suma = 0.0;

for (T e : agregado) { suma = suma + Expresion; }

 

Si   la   fuente  de  datos   fuera  un  array  entonces  el  esquema  se  puede  realizar  de  dos  maneras:  usando  un  for  extendido  como  en  el  caso  anterior  o  usando  un  for  clásico.  Las  dos  formas  son:  

 

T[] agregado = ...; Double suma = 0.0;

for (T e : agregado) { if (Filtro) { suma = suma + Expresion; } }

 

T[] agregado = ...; Double suma = 0.0;

for (int i = 0; i < agregado.length; i++) { T e = agregado[i]; if (Filtro) { suma = suma + Expresion; } }

 

Donde  podemos  hacer  los  mismos  comentarios  sobre  el  tipo  del  valor  a  acumular.  Si  la  fuente  de  datos  fuera  una  secuencia  de  números  reales,  por  ejemplo  una  secuencia  aritmética  desde  a1  hasta  a2  con  razón  a3,  entonces  el  esquema  usaría  un  for  clásico  tal  como  se  muestra  abajo:  

 

Double suma = 0.0; for (Double e = a1; e <= a2; e = e+a3) {

if (Filtro) {

Page 7: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  7  5.  Tratamientos  secuenciales  

suma = suma + Expresion; } }

 

El   agregado   de   partida   puede   tener   una   estructura  más   compleja.   Veamos   simplemente   un  ejemplo  el  caso  de  un  agregado  de  tipo   Iterable<T>  y  donde  cada  objeto  de  tipo  T   tiene  una  propiedad  P1  de  tipo  Iterable<T2>.  Supongamos  que  queremos  calcular  la  suma  de  los  valores  devueltos  por  una  expresión  sobre  los  elementos  de  tipo  T2  que  pasen  un  filtro.  Ahora  hay  que  utilizar   dos   for   extendidos   anidados.   El   primero   recorre   el   iterable   exterior   y   el   segundo  recorre  cada  uno  de  los  elementos  que  forman  parte  de  la  propiedad  P1.    

Iterable<T> agregado = ...; Double suma = 0.0;

for (T e : agregado) { for(T2 e1 : e.getP1()){ if (Filtro) { suma = suma + Expresion; } } }

 

Ahora  Filtro  es  una  expresión  construida  sobre  la  variable  e1  y  que  devuelve  Boolean  teniendo  en  cuenta  los  posibles  valores  null.  La  Expresión  se  construye  sobre  la  variable  e1  y  devuelve  Double.  Este  esquema  podría  ser  extendido  a  niveles  mayores  de  anidamiento.      En  todos  los  casos  el  resultado  quedaría  en  la  variable  suma.    

En   los   esquemas   siguientes   sólo  mostramos   la   versión   cuando   la   fuente  de  datos  es  de   tipo  Iterable<T>   asumiendo   que   los   esquemas   para   fuente   de   datos   de   los   otros   tipos   citados  pueden  ser  obtenidos  fácilmente.  

 

2.2 Producto  

 Objetivo:   Producto   de   los   valores   calculados   por   la   expresión   sobre   los   elementos   que  cumplen  el  filtro.    

• Objetivo:  Multiplicar   los  valores  calculados  por   la  expresión  sobre   los  elementos  que  cumplen  el  filtro.  

• Tipo  del  acumulador:  Double,  Integer  u  otro  tipo  numérico.    • Valor  Inicial:  Uno  • Expresión  acumuladora:  El  acumulador  por  la  expresión.  • Operador  binario:  *  • Invariante:   la   variable   producto   contiene   el   resultado   demultiplicar   los   valores   de   la  

Expresión   calculados   sobre   aquellos   elementos   recorridos   hasta   ese   momento   que  cumplen  la  condición  de  Filtro.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

Page 8: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 8   Introducción  a  la  Programación  

   

Iterable<T> agregado = ...; Double producto = 1.0;

for (T e : agregado) { if (Filtro) { producto = producto * Expresion; } }

   

El  resultado  quedaría  en  la  variable  producto.    

 2.3 Contador  

• Objetivo:  Cuenta  el  número  de  elementos  que  cumplen  el  filtro  • Tipo  del  acumulador:  Integer  • Valor  Inicial:  0  • Expresión  acumuladora:  Sumar  uno  al  acumulador  • Invariante:   la   variable  num  contiene  el   resultado  de   contar   el   número  de  elementos    

recorridos  hasta  ese  momento  que  cumplen  la  condición  de  Filtro.  • Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:    

Iterable<T> agregado = ...; Integer num = 0;

for (T e : agregado) { if (Filtro) { num = num + 1; } }

 El  resultado  quedaría  en  la  variable  num.    

 2.4 Selecciona  Lista  

• Objetivo:  Devuelve  en  una  Lista  con  los  valores  calculados  por  una  expresión  sobre  los  objetos  que  pasan  el  filtro.  

• Tipo  del  acumulador:  List<T2>  • Valor  Inicial:  Lista  Vacía.  • Operador  binario:  add  • Invariante:  la  variable  acumulador  contiene  una  lista  con  los  valores  calculados  por  la  

expresión  sobre  los  elementos  recorridos  que  cumplen  la  condición  de  Filtro.  • Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...; List<T2> lrr = new ArrayList();

for (T e : agregado) {

Page 9: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  9  5.  Tratamientos  secuenciales  

if (Filtro) { lrr.add(Expresion); } }

 El  resultado  quedaría  en   la  variable   lr.  La  Expresión   tiene  que  devolver  un  valor  del  tipo  T2  a  partir  de  un  elemento  de  tipo  T.  

 

2.5 Selecciona  Conjunto  • Objetivo:  Devuelve  un  Conjunto  con  los  valores  calculados  por  una  expresión  sobre  los  

objetos  que  pasan  el  filtro.  • Tipo  del  acumulador:  Set<T>  • Valor  Inicial:  Conjunto  Vacío.  • Operador  binario:  add  • Invariante:  la  variable  acumulador  contiene  un  conjunto  con  los  valores  calculados  por  

la  expresión  sobre  los  elementos  recorridos  que  cumplen  la  condición  de  Filtro.  • Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...; Set<T2> sr = new HashSet();

for (T e : agregado) { if (Filtro) { sor.add(Expresion); } }

 El  resultado  quedaría  en  la  variable  sr.  La  Expresión  tiene  que  devolver  un  valor  del  tipo  T2  a  partir  de  un  elemento  de  tipo  T.  

 

2.6 Selecciona  Array  • Objetivo:   Devuelve   un   array   con   los   valores   calculados   por   una   expresión   sobre   los  

objetos  que  pasan  el  filtro.  • Invariante:   la   variable   ar   contiene   los   valores   calculados   por   la   expresión   sobre   los  

elementos  recorridos  que  cumplen  la  condición  de  Filtro  en  las  posiciones  que  van  de  0  a  i-­‐1  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...; T2[] ar ; Integer num = 0;

for (T e : agregado) { if (Filtro) { num++; }

}

Page 10: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 10   Introducción  a  la  Programación  

int i = 0; ar = new T2[num];

for (T e : agregado) { if (Filtro) { ar[i] = Expresion; i++; } }

 El  resultado  quedaría  en  la  variable  ar.  La  Expresión  tiene  que  devolver  un  valor  del  tipo  T2  a  partir  de  un  elemento  de  tipo  T.    

El  esquema  es  más  complejo  que  en  el  caso  de  seleccionar  listas  o  conjuntos.  La  razón  es  que  los   array   son   agregados   de   datos   de   tamaño   constante.   Por   lo   tanto   debemos   conocer   su  tamaño  para  poder  crearlos.  Para  poder  hacerlo  debemos  contar   los  elementos  que  pasar  el  filtro,  luego  crear  un  array  de  ese  tamaño  y  por  último  colocar  los  sucesivos  valores  calculados  en   las   casillas   que   tienen   un   índice   i   dado.   El   índice   se   irá   actualizando   a  media   que   vamos  encontrando  objetos  que  pasan  el  filtro.  

 2.7 Ejecuta  Para  Todo  

• Objetivo:  Ejecuta  una  acción  sobre  cada  objeto  que  pase  el  filtro.  • Tipo  del  acumulador:  No  hay  • Valor  Inicial:  No  hay  • Operador  binario:  No  hay  • Invariante:  Se  ha  ejecutado   la  Accion   sobre   los  elementos   recorridos  que  cumplen   la  

condición  de  Filtro.  • Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...;

for (T e : agregado) { if (Filtro) { Accion; } }

   Una   acción   es   una   sentencia   construida   sobre   la   variable   e   que   puede   producir   efectos  laterales  sobre  la  misma.  Es  decir  cambiar  su  estado.      Veamos  ahora  el  segundo  bloque:  operaciones  que  pueden  calcular  su  valor  en  muchos  casos  sin  recorrer  completamente  el  agregado.  Los  esquemas  tienen  una  estructura  similar  pero   la  iteración  puede  terminar,  con  la  sentencia  break,  cuando  ya  se  conozca  el  resultado.  El  código  debe  tratar  el  primer  elemento  de  una  forma  especial.    2.8 Para  Todo  

• Objetivo:  Decide  si  todos  los  elementos  filtrados  cumplen  una  propiedad  representada  por  Expresion.  

Page 11: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  11  5.  Tratamientos  secuenciales  

• Tipo  del  acumulador:  Boolean  • Valor  Inicial:  true  • Operador  binario:  &&  • Invariante:  la  variable  r  es  verdadera  si  los  valores  calculados  por  la  expresión  sobre  los  

elementos  recorridos  que  cumplen  la  condición  de  Filtro  son  todos  verdaderos  en  otro  caso  tiene  el  valor  falso.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...; Boolean r = true;

for (T e : agregado) { if (Filtro) { r = r && Expresion; if(!r) break; } }

 Ahora   Filtro   y   Expresion   son   dos   expresiones   construidas   sobre   la   variable   e   que   devuelven  Boolean.  Dadas  las  propiedades  del  operador  &&  una  vez  que  la  variable  r  tome  el  valor  false,  es  decir  la  Expresion  devuelve  false  sobre  un  elemento  que  pasa  el  Filtro,  permanecerá  a  false  hasta  el  final  de  la  iteración.  Por  ello  es  posible  salirse  del  bucle  cuando  r  sea  false.  El  resultado  queda  en  la  variable  r.    Dado  que  la  variable  r  cambia  de  valor,  de  true  a  false,  cuando  Expresion  devuelve  false  y  en  ese  momento  nos  salimos  del  bucle  el  valor  de  r  es  simpre  el  mismo  que  el  de  la  Expresion.  Es  decir   true   hasta   que   aparece   un   valor   false   para   Expresion.   Obtenemos   un   esquema  equivalente   si   sustituimos   r   =   r   &&   Expresion   por   r   =   Expresion.   Por   lo   tanto   el   esquema  anterior  es  equivalente  a:    

Iterable<T> agregado = ...; Boolean r = true;

for (T e : agregado) { if (Filtro) { if(!Expresion){ r = false; break; } } }

   2.9 Existe  

• Objetivo:   Decide   si   alguno   de   los   elementos   filtrados   cumplen   una   propiedad  representada  por  Expresion  

• Tipo  del  acumulador:  Boolean  • Valor  Inicial:  false  • Operador  binario:  ||  

Page 12: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 12   Introducción  a  la  Programación  

• Invariante:   la  variable  r  es  verdadera  si  alguno  de  valores  calculados  por   la  Expresión  sobre   los   elementos   recorridos   que   cumplen   la   condición   de   Filtro   es   verdadero   en  otro  caso  tiene  el  valor  falso.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  

 Iterable<T> agregado = ...;

Boolean r = false; for (T o : agregado) { if (Filtro) { r = r || Expresion; if(r) break; } }

 Ahora   Filtro   y   Expresion   son   dos   expresiones   construidas   sobre   la   variable   e   que   devuelven  Boolean.  Dadas  las  propiedades  del  operador  ||  una  vez  que  la  variable  r  tome  el  valor  true,  es  decir   la   Expresion   devuelve   true   sobre   un   elemento   que   pasa   el   Filtro,   permanecerá   a   true  hasta  el  final  de  la  iteración.  Por  ello  es  posible  salirse  del  bucle  cuando  r  sea  true.  El  resultado  queda  en  la  variable  r.    Dado  que  la  variable  r  cambia  de  valor,  de  f  a  false,  cuando  Expresion  devuelve  false  y  en  ese  momento  nos   salimos   del   bucle   el   valor   de   r   es   simpre   el  mismo  que   el   de   la   Expresion.   Es  decir   true   hasta   que   aparece   un   valor   false   para   Expresion.   Obtenemos   un   esquema  equivalente   si   sustituimos   r   =   r   &&   Expresion   por   r   =   Expresion.   Por   lo   tanto   el   esquema  anterior  es  equivalente  a:    Dado  que   la  variable  r  cambia  de  valor,  de   false  a  true,  cuando  Expresion  devuelve  true  y  en  ese   momento   nos   salimos   del   bucle   tenemos   que   el   valor   de   r   será   el   mismo   si   r   =   r   ||  Expresion  por  r  =  Expresion.  Por  lo  tanto  el  esquema  anterior  es  equivalente  a:      

Iterable<T> agregado = ...; Boolean r = false;

for (T e : agregado) { if (Filtro) { if(Expresion){ r = true; break; } } }

   2.10 Busca  Primero  

• Objetivo:   buscar,   si   existe,   el   primer   objeto,   de   entre   los   filtrados,   que   cumple   una  propiedad   representada   por   Expresion.   Si   no   existe   dispara   la   excepción  NoSuchElementException  

• Tipo  del  acumulador:  Boolean  

Page 13: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  13  5.  Tratamientos  secuenciales  

• Valor  Inicial:  false  • Operador  binario:  ||  • Invariante:   la  variable  r  es  verdadera  si  alguno  de  valores  calculados  por   la  Expresión  

sobre   los   elementos   recorridos   que   cumplen   la   condición   de   Filtro   es   verdadero   en  otro  caso  tiene  el  valor  falso.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  Es  el  caso  concreto  del  esquema  existe  pero  donde  devolvemos  el  elemento  

encontrado  en  vez  de  un  valor  lógico.  Las  dos  posibilidades  son:      Iterable<T> agregado = ...;

Boolean r = false; T elemento = null; for (T o : agregado) { if (Filtro) { r = r || Expresion; if(r) { elemento = null; break; } } } if(elemento == null) throw new NoSuchElementException();

 O  equivalentemente,  siguiendo  la  segunda  versión  del  esquema  Existe:  

 

Iterable<T> agregado = ...; T elemento = null;

for (T e : agregado) { if (Filtro) { if(Expresion){ elemento = e; break; } } } if(elemento == null) throw new NoSuchElementException();

 

Como  vemos  en  este  esquema  el  resultado  queda  en  la  variable  elemento.  La  variable  r  se  hace  innecesaria  en  la  segunda  versión  del  esquema.  

 

2.11 Posición  del  Primero  • Objetivo:   buscar,   si   existe,   la   posición   del   primer   objeto,   de   entre   los   filtrados,   que  

cumple  una  propiedad  representada  por  Expresion.  Si  no  existe  devuelve  -­‐1.  Tipo  del  acumulador:  Boolean  

• Valor  Inicial:  false  • Operador  binario:  ||  

Page 14: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 14   Introducción  a  la  Programación  

• Invariante:   la  variable  r  es  verdadera  si  alguno  de  valores  calculados  por   la  Expresión  sobre   los   elementos   recorridos   que   cumplen   la   condición   de   Filtro   es   verdadero   en  otro  caso  tiene  el  valor  falso.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:  Es  el  caso  concreto  del  esquema  existe  pero  donde  devolvemos  un  entero  con  

la   posición   en   vez   de   un   valor   lógico.   Necesitamos,   además,   una   variable   que  mantenga  el  valor  de  la  posición.  .  Las  dos  posibilidades  son:      Iterable<T> agregado = ...;

Boolean r = false; int r = -1; int pos = 0; for (T o : agregado) { if (Filtro) { r = r || Expresion; if(r) { r = pos; break; } } pos++; }

 O  equivalentemente,  siguiendo  la  segunda  versión  del  esquema  Existe:  

 

Iterable<T> agregado = ...; int r = -1; int pos = 0; for (T e : agregado) { if (Filtro) { if(Expresion){ r = pos; break; } } pos++; }

 

Como  vemos  en  este  esquema  el  resultado  queda  en  la  variable  r  que  ahora  es  de  tipo  entero.    

 Veamos  ahora  algunos  valores  acumulados  que  dependen  de  órdenes.    2.12 Máximo:    

• Objetivo:   Calcula   el   máximo   de   los   valores   calculados   por   una   expresión   sobre   los  elementos  que  cumplen  el  filtro.  El  máximo  se  calcula  con  respecto  a  un  orden  dado.  Si  el  agregado  es  vacío  o  no  hay  elementos  que  pasen  el  filtro  devuelve  una  excepción.  

• Tipo  del  acumulador:  T2.    

Page 15: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  15  5.  Tratamientos  secuenciales  

• Valor   Inicial:   null   considerado,   como   veremos,   como   un   valor   menor   que   cualquier  otro  del  tipo  

• Expresión  acumuladora:  El  máximo  según  un  orden  del  acumulador  y  la  Expresión.  • Operador  binario:  max  dado  un  orden.  • Invariante:   la  variable  elMax   contiene  el  valor  máximo  de   los  valores  de   la  Expresión  

calculados   sobre   aquellos   elementos   recorridos   hasta   ese  momento   que   cumplen   la  condición  de  Filtro.  Si  no  hubiera  ninguno  el  valor  sería  null.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código  

 Iterable<T> agregado = ...; Ordering<T2> ord = ...; Ordering<T2> ord1 = ord.nullsFirst(); T2 elMax = null;

for (T e : agregado) { if (Filtro) { elMax = ord1.max(elMax,Expresion); } } if(elMax == null) throw new NoSuchElementException();

 El  resultado  queda  en  la  variable  elMax.  La  Expresión  tiene  que  devolver  un  valor  del  tipo  T2  a  partir  de  un  elemento  de   tipo  T.  El  diseño  se  basa  el  escoger  un  valor,  que  es  el  menor  que  todos   los   valores   del   tipo   en   cuestión,   para   inicializar  elMax.  Escogemos  null   como   es   valor  para  todos  los  tipos.    

Usamos   las   posibilidades   de   la   clase   Ordering   vista   en   el   tema   anterior   para   simplificar   el  código.  En  la  línea  segunda  inicializamos  un  objeto  de  tipo  Ordering  a  partir  del  orden  natural  de  un  tipo,  a  partir  de  un  Comparator  u  otras  posibilidades  que  se  ofrecen  por   la  clase.  Para  conseguir   que   según   un   orden   dado   el   valor   null   sea  menor   que   todos   los   valores   del   tipo  obtenemos  un  nuevo  objeto  de  tipo  Ordering  mediante  el  método  nullFirst().    Como  vemos  el  diseño  es  similar  al  caso  del  esquema  suma.  Otra  forma  posible  es  reforzar  el  filtro  para  eliminar  todos  los  objetos  que  son  menores  que  el  mayor  encontrado  hasta  ahora  y  actualizar  del  el  objeto  máximo  encontrado.    

Iterable<T> agregado = ...; Ordering<T2> ord = ...; Ordering<T2> ord1 = ord.nullsFirst(); T2 elMax = null;

for (T e : agregado) { if (Filtro && ord1.compare(Expresion,elMax) > 0) { elMax = Expresion; } } if(elMax == null) throw new NoSuchElementException();

   El   diseño   anterior   para   el  máximo   se   ha   basado   en   escoger   un   primer   valor   para   elMax   es  menor  que  cualquier  valor  para  el  tipo.  Otra  posibilidad  es  escoger  para  elMax  el  primer  valor  

Page 16: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 16   Introducción  a  la  Programación  

del  agregado.  Esto  se  consigue  haciendo  un  tratamiento  específico  del  primer  elemento.  Esta  técnica  puede  ser  usada  en  otros  contextos.  Consiste  en  definir  una  variable  de  tipo  boolean  inicializada  a   true  que  cambia   su  valor  cuando  hacemos  el   tratamiento  específico  del  primer  elemento.  El  esquema  de  cálculo  del  máximo  es  de  la  forma:    

Iterable<T> agregado = ...; Ordering<T2> ord = ...; T2 elMax = null; Boolean esElPrimero = true;

for (T e : agregado) { if (Filtro) { if(esElPrimero){ elMax = Expresion; esElPrimero = false; } else { elMax = ord.max(elMax,Expresion); } } } if(elMax == null) throw new NoSuchElementException();

 Como   vemos   ahora   el   orden   no   debe   preocuparse   por   los   valores   nulos.   Esta   misma   idea  puede  usarse  en  la  variante  del  esquema  que  refuerza  el  filtro  en  la  forma:    

Iterable<T> agregado = ...; Ordering<T2> ord = ...; T2 elMax = null; Boolean esElPrimero = true;

for (T e : agregado) { if (Filtro) { if(esElPrimero){ elMax = Expresion; esElPrimero = false; } else if (ord.compare(Expresion,elMax) > 0 ) { elMax = Expresion; } } } if(elMax == null) throw new NoSuchElementException();

 Cuando   el   tipo   T2   se   instancia   a   algunos   tipos   particulares   (como   Integer,   Double,   etc.)  conocemos  un  valor  del  tipo  que  es  menor  que  todos  los  demás  y  la  expresión  para  decidir  si  un  valor  del  tipo  es  mayor  que  otro  es  sencilla  el  esquema  puede  concretarse  más.  Un  ejemplo  con  T2  instanciado  a  Integer:    

Iterable<T> agregado = ...; Integer elMax = Integer.MIN_VALUE;

for (T e : agregado) { if (Filtro && Expresion > elMax) { elMax = Expresion;

} } if(elMax == Integer.MIN_VALUE) throw new NoSuchElementException();

Page 17: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  17  5.  Tratamientos  secuenciales  

 O  usando  la  técnica  de  tratar  específicamente  el  primer  elemento  y  sin  asumir  un  valor  que  sea  menor  que  todos  los  del  tipo:      

Iterable<T> agregado = ...; Ordering<T2> ord = ...; Integer elMax = null; Boolean esElPrimero = true;

for (T e : agregado) { if (Filtro) { if(esElPrimero){ elMax = Expresion; esElPrimero = false; } else if (Expresion > elMax) { elMax = Expresion; } } } if(elMax == null) throw new NoSuchElementException();

 Ahora   inicializar   elMax   a   null   solamente   nos   sirve   para   decidir   al   final   si   ha   habido   algún  elemento  que  haya  pasado  el  filtro.      2.13 Mínimo:    

• Objetivo:   Calcula   el   mínimo   de   los   valores   calculados   por   la   expresión   sobre   los  elementos  que  cumplen  el  filtro.  El  mínimo  se  calcula  con  respecto  a  un  orden  dado.  Si  el  agregado  es  vacío  o  no  hay  elementos  que  pasen  el  filtro  devuelve  una  excepción.  

• Tipo  del  acumulador:  T2.    • Valor  Inicial:  null  considerado,  como  veremos,  como  un  valor  mayor  que  cualquier  otro  

del  tipo  • Expresión  acumuladora:  El  mínimo  según  un  orden  del  acumulador  y  la  Expresión.  • Operador  binario:  min  dado  un  orden.  • Invariante:   la   variable  elMin   contiene   el   valor  mínimo  de   los   valores   de   la  Expresión  

calculados   sobre   aquellos   elementos   recorridos   hasta   ese  momento   que   cumplen   la  condición  de  Filtro.  Si  no  hubiera  ninguno  el  valor  sería  null.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código  

 Iterable<T> agregado = ...; Ordering<T2> ord = ...; Ordering<T2> ord1 = ord.nullsLast(); T2 elMin = null;

for (T e : agregado) { if (Filtro) { elMin = ord1.min(elMin,Expresion); } }

if(elMin == null) throw new NoSuchElementException();

 

Page 18: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 18   Introducción  a  la  Programación  

El  resultado  queda  en  la  variable  elMin.  La  Expresión  tiene  que  devolver  un  valor  del  tipo  T2  a  partir  de  un  elemento  de  tipo  T.  

Como  anteriormente  usamos   las  posibilidades  de   la   clase  Ordering   vista  en  el   tema  anterior  para  simplificar  el  código.  En  la  segunda  línea  inicializamos  un  objeto  de  tipo  Ordering  a  partir  del  orden  natural  de  un  tipo,  a  partir  de  un  Comparator  u  otras  posibilidades  que  se  ofrecen  por   la   clase.   Para   conseguir  que   según  un  orden  dado  el   valor  null   sea  mayor  que   todos   los  valores  del  tipo  obtenemos  un  nuevo  objeto  de  tipo  Ordering  mediante  el  método  nullLast().    Como  vemos  el  diseño  es  similar  al  caso  del  esquema  suma.  .  Otra  forma  posible  es  reforzar  el  filtro  para  eliminar  todos  los  objetos  que  son  mayores  que  el  mayor  encontrado  hasta  ahora  y    actualizar  del  el  objeto  máximo  encontrado.    

Iterable<T> agregado = ...; Ordering<T2> ord = ...; Ordering<T2> ord1 = ord.nullsLast(); T2 elMin = null;

for (T e : agregado) { if (Filtro && ord1.compare(Expresion,elMin) < 0) { elMin = Expresion; } } if(elMin == null) throw new NoSuchElementException();

   Como   en   el   caso   del   máximo   hay   otra   alternativa   haciendo   un   tratamiento   específico   del  primer  elemento.  El  esquema  de  cálculo  del  mínimo  es  de  la  forma:    

Iterable<T> agregado = ...; Ordering<T2> ord = ...; T2 elMin = null; Boolean esElPrimero = true;

for (T e : agregado) { if (Filtro) { if(esElPrimero){ elMax = Expresion; esElPrimero = false; } else { elMax = ord.min(elMax,Expresion); } } } if(elMin == null) throw new NoSuchElementException();

 Como   en   el   caso   del   máximo   el   orden   no   debe   preocuparse   por   los   valores   nulos.   O   en   la  variante  de  reforzar  el  filtro:      

Iterable<T> agregado = ...; Ordering<T2> ord = ...; T2 elMin = null;

Boolean esElPrimero = true; for (T e : agregado) {

Page 19: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  19  5.  Tratamientos  secuenciales  

if (Filtro) { if(esElPrimero){ elMin = Expresion; esElPrimero = false; } else if (ord.compare(Expresion,elMax) < 0 ) { elMin = Expresion; } } } if(elMin == null) throw new NoSuchElementException();

   Y  de  forma  similar  cuando  el   tipo  T2  se   instancia  a  algunos  tipos  particulares   (como   Integer,  Double,  etc.):        

Iterable<T> agregado = ...; Integer elMin = Integer.MAX_VALUE;

for (T e : agregado) { if (Filtro && Expresion < elMax) { elMax = Expresion; } } if(elMax == Integer.MAX_VALUE) throw new NoSuchElementException();

 O  usando  la  técnica  de  tratar  específicamente  el  primer  elemento  y  sin  asumir  un  valor  que  sea  menor  que  todos  los  del  tipo:      

Iterable<T> agregado = ...; Ordering<T2> ord = ...; Integer elMax = null; Boolean esElPrimero = true;

for (T e : agregado) { if (Filtro) { if(esElPrimero){ elMax = Expresion; esElPrimero = false; } else if (Expresion < elMax) { elMax = Expresion; } } } if(elMax == null) throw new NoSuchElementException();

   2.14 Iteración  Genérica  

• Objetivo:   Acumular   los   valores   calculados   por   la   expresión   sobre   los   elementos   que  cumplen  el   filtro  según   la  operación  contenida  en  un  objeto  de  tipo  Acumulator.Este  objeto,  con  el  tipo  que  se  explica  abajo,  define  una  operación  para  acumular  y  un  valor  inicial  para  los  valores  a  acumular.  

• Tipo  del   acumulador:  Acumulator<T>Valor   Inicial:   El   establecido  en  el   objeto  de   tipo  Acumulator  

• Expresión  acumuladora:  El  acumulador  más  la  expresión.  • Operador  binario:  El  definido  en  el  objeto  de  tipo  Acumulator  

Page 20: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 20   Introducción  a  la  Programación  

• Invariante:  La  variable  acum  contiene  el  resultado  de  acumular  sumar  los  valores  de  la  Expresión   calculados   sobre   aquellos   elementos   recorridos   hasta   ese   momento   que  cumplen  la  condición  de  Filtro.  

• Función  de  Cota:  el  número  de  elementos  del  agregado  que  faltan  por  recorrer.  • Código:    

Iterable<T> agregado = ...; Acumulator<T2> acum =...; acum.setInitial();

for (T e : agregado) { if (Filtro) { acum.add(Expresion); if(acum.isDone()) break; } } T2 r = acum.getValue(); if(r == null) throw new NoSuchElementException();

 

Filtro  es  una  expresión  sobre   la  variable  e  que  devuelve  boolean.  Esta  expresión  que  hace  el  papel  de  Filtro  debe  tener  en  cuenta  en  su  caso  la  posibilidad  de  que  algún  valor  sea  null  como  se  ha  explicado  más  arriba.  Expresion  es  una  expresión  sobre  la  variable  e  que  devuelveT2.  El  resultado,  si  existe,  queda  en  la  variable  r.    

En   el   código   anterior   hemos   usado   el   tipo   Acumulator<T>.   Este   tipo   viene   definido   por   la  interfaz:  

 

public interface Acumulator<T> { void setInitial(); void add(T e); T getValue(); boolean isDone(); }

 

El  tipo  Acumulator<T>  ofrece  los  siguientes  métodos:  

• setInitial():  Situa  el  acumulador  en  su  estado  incial  • add(T  e):  Acumula  el  valor  e.  • getValue():  Devuelve  el  valor  acumulado  • isDone():  Verdadero  si  podemos  ya  conocer  el  valor  final  sin  recorrer  todo  el  agregado.  

Asumimos  que  si  el  valor  devuelto  por  el  acumulador  es  null  es  que  nos  e  ha  encontrado  un  valor  válido.  

Este   esquema   engloba   a   todos   los   anteriores.   Casos   particulares   pueden   ser   acumuladores  para   calcular   la   suma   de   un   Iterable   de   Racionales.   En   este   caso   la   implementación   del  acumulador  sería:  

 

public class SumaRacional implements Acumulator<Racional> {

Page 21: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  21  5.  Tratamientos  secuenciales  

private Racional r = null; public SumaRacional() { } @Override public void setInitial()() { r = Racionales.create(); } @Override public void add(Racional e) { r.suma(e); } @Override public Racional getValue() {return r; } @Override public boolean isDone()() { return false; } }

 Otro  caso  particular  puede  ser  un  acumulador  para  calcular  el  máximo  según  un  orden:    

public class Maximo<T> implements Acumulator<T> { private Racional r = null; private Comparator<> ord = null; private boolean esPrimero = true; private elMax = null; public Maximo(Comparator<> ord) { this.ord = ord; } @Override public void setInitial()() { esPrimero = true; } @Override public void add(T e) { if(esPrimero){ elMax = e; esPrimero = false; } else if(ord.compare(e,elMax) > 0) { elMax = e; } } @Override public T getValue() {return r; } @Override public boolean isDone()() { return false; } }

 Igualmente   podemos   diseñar   acumuladores   para   el   resto   de   los   esquemas:  mínimo,   buscar,  existe,  para  todo,  etc.  Dejamos  su  implementación  como  ejercicio.    Combinando   la   iteración   genérica   y   un   acumulador   específico   podemos   obtener   esquemas  para  caso  concretos.  En  el  caso  anterior  de  la  suma  de  Racionales:    

Page 22: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 22   Introducción  a  la  Programación  

Iterable<Racional> agregado = ...; Racional acum = Racionales.create();

for (T e : agregado) { if (Filtro) { acum.suma(e); } }

 El   resultado  queda  en   la  variable  acum.  Este  tratamiento  genérico  puede  combinarse  con  un  tratamiento  específico  para  el  primer  elemento  si  fuera  necesario.  

 2.15 Algoritmos  para  grupos  consecutivos  de  elementos:    

Podemos  diseñar  también  esquemas  secuenciales  para  grupos  consecutivos  de  elementos.  Son  generalizaciones   de   los   anteriores   donde   el   Filtro   y   la   Expresion   dependen   ahora   de   varias  variables.  

Solo   presentamos   la   generalización   de   Para   Todo,   Existe   y   Contar,   para   grupos   de   dos  elementos  consecutivos,  sin  recordar  todos  los  detalles  de  los  mismos.  La  generalización  a  más  elementos   consecutivos   puede   hacerse   fácilmente.   Igual   podemos   decir   del   resto   de   losm  esquemas:    

Contar  Dos:    

 Iterable<T> agregado = ...; Boolean r = true; T elAnterior = null; Integer num = 0; Boolean esPrimero = true; for (T e : agregado) { if (Filtro2(elAnterior,e)) { if(esPrimero){ elAnterior = e; esPrimero = false; } else { num++; elAnterior = e; } } }

 

El  resultado  queda  en  la  variable  num.    

 

Para  Todo  Dos:    

 Iterable<T> agregado = ...; Boolean r = true; T elAnterior = null; Boolean esPrimero = true; for (T e : agregado) { if (Filtro2(elAnterior,e)) {

Page 23: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  23  5.  Tratamientos  secuenciales  

if(esPrimero){ elAnterior = e; esPrimero = false; } else { r = r && Expresion2(elAnterior,e);

elAnterior = e; if(!r) break; } } }

 El  resultado  queda  en  la  variable  r.  Expresion2  devuelve  un  valor  lógico.  

Existe  Dos:      

 Iterable<T> agregado = ...; Boolean r = false; T elAnterior = null; Boolean esPrimero = true; for (T e : agregado) { if (Filtro2(elAnterior,e)) { if(esPrimero){ elAnterior = e; esPrimero = false; } else { r = r || Expresion2(elAnterior,e);

elAnterior = e; if(r) break; } } }

 El  resultado  queda  en  la  variable  r.  Expresion2  devuelve  un  valor  lógico.  

 Casos  particulares  de  los  esquemas  anteriores  son:    

• Comprobar   si   un   iterable   está   ordenado   o   estrictamente   ordenado.   En   este   caso  Expresion2(elAnterior,e) se  sustituirá  (en  el  esquema  Para  Todo  Dos)  por  la  expresión  que   sea   verdadera   si  elAnterior   es  menor   o   igual   o  menor   que   e   (posiblemente   con  respecto  a  un  orden).  El  Filtro2  será  true.  

• Comprobar  si  existen  dos  elementos  iguales  consecutivos.  • Contar   cuantos   pares   de   elementos   consecutivos   hay   que   cumplan   una   propiedad  

dada.      3. Ejemplos  y  Metodología  de  trabajo    Los   esquemas   anteriores   se   repiten   muy   frecuentemente.   Para   poder   usarlos   debemos  identificar  en  primer  lugar  cada  uno  de  sus  elementos:    

Page 24: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 24   Introducción  a  la  Programación  

• ¿Cuál  es  el  agregado  y  su  tipo  (Iterable,  array,  secuencia)?  Es  simple  o  complejo?  • ¿Cuál  es  el  filtro  si  lo  hay?  • ¿Cuál  es   la  expresión  a  acumular   (o  alternativamente   la  acción  a   llevar  a   cabo   sobre  

cada  elemento)?  • ¿Hay  que  tener  en  cuenta  algún  orden?    • ¿Cuál  de  los  esquemas  usar?  

 Para  los  ejemplos  siguientes  suponemos  implementados  los  tipos  propuestos  como  ejercicios  en  el  tema  anterior.      Ejemplo:    Si  queremos  diseñar  un  método  static  de  la  clase  Personas,  tomando  como  parámetro  una  lista  de  Persona  y  una  edad  que  debe  ser  positiva,  devuelva  como  resultado  la  suma  de  las  edades  de  las  personas  contenidas  en  la  lista  que  sean  mayores  que  al  edad  dada.  No  hay  garantías  de  que  los  objetos  en  la  lista  sean  distintos  de  null.  En  este  caso  tenemos:    

• Origen  de  datos:  la  lista  • Filtro:  la  persona  es  mayor  que  la  edad  proporcionada  • Expresión:  calcula  la  edad  de  una  persona  • Orden  :  no  hay  ninguno  involucrado  • Esquema  a  usar:  suma  

 El  código  resultante,  donde  puede  verse  el  código  concreto  del  Filtro  y  de  la  Expresión,  es:    

public static Integer sumaEdades(List<Persona> lista, Integer ed){ if(ed <= 0){ throw new IllegalArgumentException(); } Integer suma = 0; for (Persona e : lista) { if (e!=null && e.getEdad() > ed) { suma = suma + e.getEdad(); } } return suma; }

   Los  siguientes  ejemplos  ilustran  algunos  de  los  esquemas  secuenciales.  Todos  los  métodos  los  podemos   ubicar   en   la   clase   Racionales.   Vamos   viendo   el   enunciado,   el   código   y   algunos  comentarios.    Ejemplo    Dado  un  array   de  String   cada  una  de   las   cuales   representa  un   racional,  obtener  una   lista  de  racionales.  

Page 25: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  25  5.  Tratamientos  secuenciales  

 public static List<Racional> getLista (String[] ag){

List<Racional> lr = new ArrayList(); for (String e : ag) { lr.add(Racionales.create(e)); } return lr; }

 Ahora   hemos   usado   el   esquema   selecciona   lista,   no   hay   filtro   y   Racionales.create(e)   es   la  Expresión  que  construye  objetos  de  tipo  Racional.    Ejemplo    Implementar  el  método  getFotos  en  la  clase  Bibliotecas  que  dada  una  Biblioteca  y  dos  fechas,  la  segunda  mayor  que  la  primera,  devuelva  todas  las  fotos  distintas  que  contiene  que  fueron  realizadas  entre  esas  dos  fechas.    

public static Set<Foto> getFotos (Biblioteca b, Fecha f1, Fecha f2){ if(!(f1.compareTo(f2) <=0)){ throw new IllegalArgumentException(); }

Set<String> sr = new HashSet(); for (Album a : b) { for(Foto f: a.getFotos()){ Fecha ff = f.getFecha(); if(ff.compareTo(f1) > 0 && ff.compareTo(f2) < 0){ sr.add(f); } } } return sr; }

 Ahora   hemos   usado   el   esquema   selecciona   conjunto,   el   filtro   es   que   la   fecha   este  estrictamente  entre   las  dos  proporcionadas.  Suponemos  que   todas   las   fotos  son  distintas  de  null.  El  origen  de  datos  tiene  una  lista  de  álbumes  y  cada  álbum  una  lista  de  fotos.      Ejemplo    Dado  un  array  de  Racional  cada  una  de  las  cuales  representa  un  racional,  obtener  cuantos  hay  mayores  que  cero.    

public static Integer getNumeroDePositivos (Racional[] ag){ Integer num = 0; Racional cero = Racionales.create();

for (Racionale : ag) { if(e!=null && e.compareTo(cero)){ num++;

}

Page 26: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 26   Introducción  a  la  Programación  

} return num; }

 Ahora   hemos   usado   el   esquema   contar,   el   filtro   es   que   el   racional   sea   distinto   de   null   y  positivo.   Vemos   también   que   cuando   una   expresión   tenemos   que   usarla   repetidamente   y  siempre   y   sabemos   que   siempre   devolverá   el   mismo   valor   es   conveniente   hacer   el   cálculo,  guardar  el  resultado  en  una  variable  local  y  usar  esta  variable  posteriormente.    Ejemplo    Dada  una  lista  de  Viaje  calcular  cuantas  ciudades  distintas  pueden  visitarse  si  hacen  todos  los  viajes  de  la  lista  que  sean  posibles  para  un  grupo  formado  por  un  número  dado  de  personas.    

public static Integer getCiudadesDistintas (List<Viaje> lista, Integer n){ if(n <= 0){ throw new IllegalArgumentException(); }

Set<String> sr = new HashSet(); for (Viaje e : ag) { if(e.getMinimoDePersonas() >= n){ for(String s: e.getCiudadesVisitadas(){ sr.add(s); } } } return sr.size(); }

 Ahora  hemos  usado  el  esquema  selecciona  conjunto,  el  filtro  es  que  el  grupo  sea  mayor  o  igual  al  entero  dado.  El  número  de  objetos  distintos  es  el  cardinal  del  conjunto  construido.  Podemos  observar  que  el  origen  de  datos  está  compuesto  de  una  lista  cada  uno  de  cuyos  objetos  tiene  una   propiedad   que   otra   lista.   También   es   interesante   constatar   que   el   filtro   depende   de   la  variable  de  tipo  Vuelo  y  no  de  la  de  tipo  String.  Esta  es  la  razón  para  poner  el  if  entre  los  dos  for.   Si   el   fitro   hubiera   dependido   de   la   ciudad,   de   tipo   String,   entonces   iría   después   del  segundo  for.    Ejemplo    Dada  una  lista  de  Polígonos  diseñar  un  método  static  que  nos  devuelva  el  que  tenga  un  área  mayor  de  entre  los  que  tengan  un  número  de  lados  dado.    

public static Poligono getMayorArea (List<Poligono> lista, int n){ Ordering<Double> ord = Ordering.from(new PorArea()); Ordering<Double> ord1 = ord.nullsFirst(); Poligono elMax = null;

for (Poligono p : lista) {

if (p!=null && p.getNumeroDeVertices() == n) { elMax = ord1.max(elMax,p); }

}

Page 27: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  27  5.  Tratamientos  secuenciales  

if(elMax == null) throw new NoSuchElementException(); return elMax; }

 Necesitamos  diseñar  un  orden  sobre  los  polígonos:  el  dado  por  sus  áreas.    

public class PorArea implements Comparator<Poligono>{ public PorArea(){ } public int compare(Poligono p1, Poligono p2){ Integer r; r = p1.getArea().compareTo(p2.getArea()); return r; } }

 Alternativamente  puesto  que  podemos  hacer  un  diseño  específico  para  este  caso  sin  tener  que  diseñar   nuevos   objetos   de   tipo   Comparator   usando   la   técnica   de   tratar   específicamente   el  primer  elemento.    

public static Poligono getMayorArea (List<Poligono> lista, int n){ Poligono elMax = null; Double areaMax = Double.MIN_VALUE; Boolean esPrimero = true; for (Poligono p : lista) { if(p!=null && p.getNumeroDeVertices() == n){ if(esPrimero) { elMax = p; esPrimero = false; else if (p.getArea() > elMax.getArea()) { elMax = p; } } } if(elMax == null) throw new NoSuchElementException(); return elMax; }

 Es  conveniente  explicitar  por  qué  p.getArea() > elMax.getArea() es  la  expresión  adecuada  para  implementar  ord.compare(Expresion,elMax) > 0  

 

Ejemplo    Dada   una   lista   de   Polinomio   diseñar   un   método   static   que   nos   devuelva   una   lista   con   sus  derivadas.      

public static List<Polinomio> getDerivadas (List<Polinomio> ag){ List<Polinomio> lr = new ArrayList();

for (Polinomio e : ag) {

lr.add(e.getDerivada());

}

Page 28: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 28   Introducción  a  la  Programación  

return lr; }

 

Ejemplo    Dado  un   Iterable   de   T   diseñar   un  método   static   que  nos   devuelva   un   String   formado  por   la  representación   en   cadenas   de   caracteres   de   los   elementos   separadas   por   comas   y   entre  corchetes.      Usaremos   un   esquema   similar   a   la   iteración   genérica   con   tratamiento   específico   del   primer  elemento.    

public static <T> String getString (Iterable<T> ag){ String s “”; Boolean esPrimero = true;

for (T e : ag) { if(esPrimero){ s = “[“+e; esPrimero = false; } else { s = “,”+e; } } s = s+”]”; return s; }

 

Ejemplo    Dada  un  Iterable  de  Complejo  diseñar  un  método  static  que  nos  devuelva  el  producto  de  todos  sus  elementos.      Podemos  resolver  con  la  Iteración  General  con  el  acumulador:    

public class MultiplicaComplejo implements Acumulator<Complejo> { private Complejo r = null; public MultiplicaComplejo() { }

@Override public void setInitial()() { r = Complejos.create(1,0); } @Override public void add(Complejo e) { r.multiplica(e); }

@Override public Racional getValue() {return r; }

@Override

public boolean isDone()() { return false; }

Page 29: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  29  5.  Tratamientos  secuenciales  

}

 Alternativamente  podemos  combinar  la  iteración  general  con  el  acumulador  concreto  para  dar  el  esquema:  

 

Iterable<Complejo> agregado = ...; Complejo acum = Complejos.create(1,0);

for (T e : agregado) { acum.multiplica(e); }

 

 

4. Conceptos  aprendidos    

• Operaciones  habituales  con  agregados  de  datos  • Elementos  comunes  a  las  operaciones  habituales:  acumulador,  filtro  y  expresión  • Esquemas  secuenciales  comunes  

     5. Ejercicios  Propuestos    

1. Dada  una  lista  de  números  enteros,  que  se  toma  como  parámetro,  implementa  un  método  static  en  la  clase  Enteros  para  cada  una  de  las  siguientes  cuestiones:  

a) ¿Todos  los  elementos  de  la  lista  son  impares?  b) ¿Existe  alguno  que  sea   impar  y  primo?  Supóngase   implementado  previamente  el  

método  esPrimo.  c) ¿Cuántos  hay?    d) ¿Cuál  es  el  valor  de  suma  de  los  que  sean  primos?  ¿Y  del  producto  de  los  que  sean  

impares?  e) ¿Hay  alguno  que  divida  a  un  número  n  (siendo  n  un  parámetro  del  método)?  f) Buscar   todos   los   enteros   pares   que   están   en   la   lista   de   entrada   (que   el  método  

devuelva  el  resultado  en  otra  lista)    

2. Dado  un  Set<List<Integer>>  que  se  toma  como  parámetro,   implementa  un  método  static  en  la  clase  Enteros  para  cada  una  de  las  siguientes  cuestiones:  

a) ¿Cuánto  vale  la  suma  de  todos  los  elementos  que  son  impares?  b) ¿Cuál  es  el  entero  más  pequeño?  ¿y  el  más  grande?  c) ¿Existe  algún  elemento  que  sea  primo?  d) ¿Existe   algún   elemento   que   sea   primo   y   que   ocupe   la   primera   posición   de   cada  

lista  del  conjunto?  e) Devolver   un   List<Integer>   con   todos   aquellos   enteros   que   ocupan   la   primera  

posición  en  cada  lista  del  conjunto.    

Page 30: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

 30   Introducción  a  la  Programación  

3. Dada   una   lista   de   números   racionales,   que   se   toma   como   parámetro,   implementa   un  método  static  en  la  clase  Racionales  para  resolver  cada  una  de  las  siguientes  cuestiones:  

a) ¿Cuál  es  el  mayor?  ¿y  el  menor?  b) ¿Todos  los  elementos  de  la  lista  tienen  valor  mayor  que  1?  c) ¿Cuál  es  el  valor  de  suma,  en  valor  real,  de  los  que  sean  menores  que  1,  en  valor  

real?    d) ¿Y  del  producto,  en  valor  real,  de  los  que  tengan  el  denominador  mayor  que  3,  en  

valor  real?  e) Realiza  los  dos  apartados  anteriores  devolviendo  un  valor  racional  f) Cuantos  racionales  distintos  hay?    

4. Dado  un  List<Set<Racional>>  que  se  toma  como  parámetro,  implementa  un  método  static  en  la  clase  Racionales  para  resolver  cada  una  de  las  siguientes  cuestiones:  

a) ¿Cuál  es  el  conjunto  que  tiene  más  elementos?  b) ¿Existe  algún  conjunto  con  un  número  impar  de  elementos?  c) Devolver   un   racional   cuyo   numerador   sea   la   suma   de   los   numeradores   y   cuyo  

denominador  el  producto  de  los  denominadores.    

5. Dado  un  Set<List<Integer>>  que  se  toma  como  parámetro,   implementa  un  método  static  en  la  clase  Enteros  para  resolver  cada  una  de  las  siguientes  cuestiones:  

a) ¿Cuál  es  la  lista  de  mayor  tamaño?  b) ¿Existe  alguna  lista  que  contenga  algún  entero  con  valor  negativo?  c) ¿Todas  las  listas  son  de  tamaño  mayor  que  2?  d) ¿Cuánto  suma  la  lista  de  todos  los  números  enteros?  

 6. En   una   biblioteca   de   fotos   digitales,   con   los   tipos   definidos   en   el   capítulo   anterior,  

implemente  los  siguientes  métodos  :    a) El  método  getTamaño  de  la  clase  Albumes,  que  devuelve  el  tamaño  total  de  las  fotos  

de  un  álbum,  que  toma  como  parámetro,  como  la  suma  de   los  tamaños  de  todas   las  fotos  del  álbum.  

b) Un  método  estático  de  la  clase  Bibliotecas  que  devuelva  un  álbum  con  las  fotos  de  una  biblioteca  que   tienen  un  descriptor  dado  y  han  sido   retocadas.  El  nombre  del  álbum  será  el  propio  descriptor.    

 7. Usando  los  tipos  del  capítulo  anterior  implemente:  

a) Un   método   llamado   beneficioTotal   que   tome   como   argumentos   un   Huerto   y   un  Integer,  y  devuelva  el  beneficio   total  del  huerto  de  aquellas  cosechas  cuyo  tiempo  de  recolección  sea  menor  al  entero  recibido.  

b) Un  método  llamado  aumentaBeneficios,  que  reciba  un  Huerto,  un  Set  <String>  y  un  Double   y  aumente  en  esa  cantidad  el  beneficio  de  aquellas  cosechas  cuyo  nombre  esté  contenido  en  el  conjunto.  

 8. Implemente   un  método   estático   en   la   clase   LectoresElectrónicos   para   responder   a   cada  

una  de  las  siguientes  preguntas.    a) Un   método   que   construya   un   Set<Libro>   con   todos   los   libros   de   un  

LectorElectrónico<Libro>   que   contengan   el   descriptor   “programación”   y   tengan  una  valoración  igual  o  superior  a  4.  

Page 31: 5 Tratamientos secuenciales - v4 · 2! IntroducciónalaProgramación!! • ¿cuánto!valelasumadeuna!expresiónde!losobjetosdelagregado?! • ¿y!el!producto!delos!queverifican!una!propiedad?!

  31  5.  Tratamientos  secuenciales  

 9. Implemente  los  siguientes  métodos  en  la  clase  Viajes:    

a) Un  método  que  devuelva  la  calificación  media  de  los  clientes  para  todos  los  viajes  en  el  catálogo.  Parámetros  de  entrada:  catálogo  de  viajes.  

b) Un   método   que   diga   si   todos   los   viajes   del   catálogo   son   de   un   operador  determinado.  Parámetros  de  entrada:  catálogo  de  viajes  y  nombre  del  operador.  

 

10. Dadas  las  siguientes  interfaces:  

public interface Destino extends Comparable<Destino>{ Double getDistancia(); String getNombre();

} public interface Vuelo {

Destino getDestino(); Double getPrecio(); Integer getNumPlazas(); Integer getNumPasajeros(); Integer getCodigo(); Fecha getFechaSalida(); Persona getPiloto();

} public interface CompañiaAerea {

Integer getCodigo(); String getNombre(); Vuelo[] getVuelos();

}  

Implemente  los  siguientes  métodos  en  la  clase  Compañias:  

a) Un  método  que  dada  una  compañía  aérea  devuelva  el  nombre  del  piloto  del  primer  vuelo  (de  salida  más  pronto)  con  plazas  libres  con  destino  París.    

b) Construya  un  método  que  dada  una  compañía  aérea  devuelva  el  código  del  vuelo  que  más  distancia  recorre  de  entre  los  que  salen  hoy.