1. Colecciones de Orden
Superior en Java
Por: Óscar López, M.Sc.
Grupo GNU/Linux de la
Universidad del Cauca
2. Agenda
• Un ejercicio en ingeniería de lenguajes
• Dos técnicas de programación
• Iteradores
• Secuencias como interfaces convencionales
• Implementación en Smalltalk
• ¿Y en Java, qué?
• Librería Higher Order Collections
• Bloques en Java
• Instanciación de colecciones
• Métodos enumeradores
• Trabajo futuro
• Bibliografía
GLUC 2005 - GNU FDL
3. Iteradores [4]
• Un patrón de diseño que permite acceder
secuencialmente los elementos de un
objeto agregado sin exponer su
implementación interna
• Se clasifican como internos y externos,
dependiendo de quién controla la iteración
• C++, Java, C# proporcionan iteradores
polimórficos externos, Smalltalk dispone de
iteradores internos
GLUC 2005 - GNU FDL
5. Secuencias Como
Interfaces Convencionales [3]
• Definen un estilo particular para manipular
estructuras de datos
• Un programa se concibe como datos
fluyendo a través de etapas de
procesamiento
• Cada secuencia de datos expone una
interfaz de operaciones convencionales
para procesar sus elementos
• Similar en intención al patrón Visitor
GLUC 2005 - GNU FDL
6. Ejemplo
• Enumere las hojas de un árbol
• Filtre, eligiendo las hojas impares
• Calcule el cuadrado de las hojas elegidas
• Acumule el valor de su sumatoria
GLUC 2005 - GNU FDL
7. Ejemplo
• Enumere los enteros de 0 hasta n
• Calcule el número Fibonacci de cada uno
• Filtre, seleccionando los pares
• Acumule el resultado en una nueva lista
GLUC 2005 - GNU FDL
9. Implementación en Smalltalk [5]
• Usa bloques: objetos de primera clase que
encierran una función anónima y el contexto en el
que ésta fue definida
• Todas las colecciones de objetos ofrecen una
interfaz convencional que permite
• Iterar sobre sus elementos
• Realizar operaciones estándar sobre sus elementos
• Las operaciones están implementadas como
funciones de orden superior que reciben un
bloque como parámetro
• En Smalltalk, este conjunto de operaciones reciben
el nombre de “métodos enumeradores”
GLUC 2005 - GNU FDL
10. Ejemplo
coll := #(1 2 3 4 5 6).
coll do: [ :e | Transcript show: e ].
coll collect: [ :e | e * e ].
coll detect: [ :e | e = 4 ].
coll select: [ :e | e < 4 ].
coll reject: [ :e | e < 4 ].
coll inject: 0 into: [ :subTotal :e | subTotal + e ].
GLUC 2005 - GNU FDL
11. Librería HigherOrderCollections
• Permite definir bloques en Java
• Extiende las colecciones de Java,
adicionándoles métodos enumeradores
como los de Smalltalk
• Disponible bajo licencia Apache 2.0 [7]
• El artículo [1] profundiza en los detalles de
la implementación
• El código fuente y la documentación se
pueden descargar en [2]
GLUC 2005 - GNU FDL
12. Librería HigherOrderCollections
Requerimientos e Instalación:
• Se debe tener instalado J2SE 1.5.0 ó superior
• Incluir en el CLASSPATH el archivo
higher-order-collections.jar
• Importar los siguientes paquetes:
import util.blocks.*;
import util.higherOrderCollections.*;
import static
util.higherOrderCollections.HOCFactory.CollectionEnum.*;
GLUC 2005 - GNU FDL
13. Bloques en Java
• ¿Cómo implemento un bloque en Java?
• ¿Cómo hago que sea seguro respecto a
tipos?
Usando clases internas anónimas y tipos
genéricos
• Existen numerosas implementaciones de
bloques, se usó una versión modificada de
“Blocks in Java” [6]
GLUC 2005 - GNU FDL
14. Bloques en Java
• Procedimientos: Retornan void al evaluarlos
• Sin parámetros : ProcedureBlock
• Con un parámetro (unario) : UnaryProcedureBlock
• Con dos parámetros (binario) : BinaryProcedureBlock
• Predicados: Retornan un valor booleano al evaluarlos
• Sin parámetros : PredicateBlock
• Con un parámetro (unario) : UnaryPredicateBlock
• Con dos parámetros (binario) : BinaryPredicateBlock
• Funciones: Retornan un tipo arbitrario al evaluarlos
• Sin parámetros : FunctionBlock
• Con un parámetro (unario) : UnaryFunctionBlock
• Con dos parámetros (binario) : BinaryFunctionBlock
GLUC 2005 - GNU FDL
15. Ejemplo
final Integer uno = 1;
FunctionBlock<Integer> bloqueSuma;
bloqueSuma = new FunctionBlock<Integer>() {
public Integer value() {
return uno + uno; }};
bloqueSuma.value();
GLUC 2005 - GNU FDL
16. Instanciación de Colecciones
• La forma más sencilla: usando la clase HOCFactory
HigherOrderCollection<Double> lista;
lista = HOCFactory.newInstance(LinkedList);
• HOCFactory proporciona adaptadores por defecto
para las siguientes colecciones:
ArrayList, ConcurrentLinkedQueue,
CopyOnWriteArrayList, CopyOnWriteArraySet,
HashSet, LinkedBlockingQueue, LinkedHashSet,
LinkedList, PriorityBlockingQueue,
PriorityQueue, Stack, TreeSet y Vector
GLUC 2005 - GNU FDL
17. Instanciación de Colecciones
• La forma más flexible: extendiendo la clase
AbstractHigherOrderCollection
• Notar que el método getCollection()
permite recuperar la colección usada
internamente por la colección de orden
superior:
HigherOrderCollection<Integer> col;
col = HOCFactory.newInstance(ArrayList);
ArrayList<Integer> lista;
lista = (ArrayList<Integer>)col.getCollection();
GLUC 2005 - GNU FDL
18. Métodos Enumeradores
void doBlock(UnaryProcedureBlock<E> aBlock)
Evalúa el bloque sobre cada uno de los
elementos de la colección
coleccion.doBlock(new UnaryProcedureBlock<Integer>() {
public void value(Integer elemento) {
System.out.print(elemento + “ ”); }});
1 2 3 4 5 6
GLUC 2005 - GNU FDL
19. Métodos Enumeradores
int count(UnaryPredicateBlock<E> aBlock)
Retorna el número de elementos que al ser
evaluados sobre el bloque hacen que éste
retorne true
coleccion.count(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento.intValue() % 2 == 0; }});
3
GLUC 2005 - GNU FDL
20. Métodos Enumeradores
E detect(UnaryPredicateBlock<E> aBlock)
Retorna el primer elemento que al ser
evaluado sobre el bloque hace que éste
retorne true
coleccion.detect(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento == 4; }});
4
GLUC 2005 - GNU FDL
21. Métodos Enumeradores
E remove(UnaryPredicateBlock<E> aBlock)
Remueve de la colección y retorna el primer
elemento que al ser evaluado sobre el bloque
hace que éste retorne true
coleccion.remove(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento == 5; }});
5
GLUC 2005 - GNU FDL
22. Métodos Enumeradores
HigherOrderCollection<E>
removeAll(UnaryPredicateBlock<E> aBlock)
Remueve de la colección todos los elementos que al ser
evaluados sobre el bloque hacen que éste retorne
true. Retorna una nueva colección con los elementos
que fueron removidos
coleccion.removeAll(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento.intValue() % 2 != 0; }});
1 3 5
GLUC 2005 - GNU FDL
23. Métodos Enumeradores
R inject(R thisValue,
BinaryFunctionBlock<R,E,R> binaryBlock)
Acumula y retorna el resultado de evaluar el bloque
sobre cada uno de los elementos. El primer parámetro
sirve como valor inicial del acumulador
coleccion.inject(0,
new BinaryFunctionBlock<Integer,Integer,Integer>() {
public Integer value(Integer acc, Integer elemento) {
return acc + elemento; }});
21
GLUC 2005 - GNU FDL
24. Métodos Enumeradores
HigherOrderCollection<R>
collect(UnaryFunctionBlock<E,R> aBlock)
Evalúa el bloque sobre todos los elementos de la
colección y va añadiendo cada valor retornado por el
bloque a una nueva colección, que finalmente es
retornada
coleccion.collect(
new UnaryFunctionBlock<Integer,Integer>() {
public Integer value(Integer elemento) {
return elemento * elemento; }});
1 4 9 16 25 36
GLUC 2005 - GNU FDL
25. Métodos Enumeradores
HigherOrderCollection<E>
select(UnaryPredicateBlock<E> aBlock)
Añade a una nueva colección los elementos que al ser
evaluados sobre el bloque hacen que éste retorne
true
coleccion.select(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento < 4; }});
1 2 3
GLUC 2005 - GNU FDL
26. Métodos Enumeradores
HigherOrderCollection<E>
reject(UnaryPredicateBlock<E> aBlock)
Añade a una nueva colección los elementos que al ser
evaluados sobre el bloque hacen que éste retorne
false
coleccion.reject(new UnaryPredicateBlock<Integer>() {
public boolean value(Integer elemento) {
return elemento < 4; }});
4 5 6
GLUC 2005 - GNU FDL
27. Trabajo Futuro
• Definir métodos enumeradores sobre las
clases que implementan la interfaz Map
• Agregar nuevos métodos enumeradores
• Agregar nuevos bloques que soporten un
número variable de argumentos
• Proporcionar un algoritmo de iteración
más eficiente para las colecciones que
implementan la interfaz RandomAccess
• Incluir un script de Ant para compilar,
probar y generar la documentación
GLUC 2005 - GNU FDL
28. Bibliografía
1. Artículo -
http://gluc.unicauca.edu.co/wiki/index.php/Colecciones_de_Or
den_Superior_en_Java
2. Código Fuente -
http://gluc.unicauca.edu.co/wiki/images/e/e5/Higher-order-
collections.tar.bz2
3. Harold Abelson, Gerald Sussman y Julie Sussman. “Structure
and Interpretation of Computer Programs”, 2da Edición.
MIT Press, 1996.
4. E. Gamma, R. Helm, R. Johnson and J. Vlissides. “Design
Patterns: Elements of Reusable Object Oriented Software”.
Addison-Wesley, 1995.
5. Adele Goldberg, David Robson. “Smalltalk-80: The Language
and Its Implementation” (El Libro Azul). Addison-Wesley, 1985.
6. Bloques en Java - http://c2.com/cgi/wiki?BlocksInJava
7. Licencia Apache 2.0 - http://www.apache.org/licenses/LICENSE-
2.0
GLUC 2005 - GNU FDL