
La clase Arrays agrupa algoritmos útiles que se aplican, en general, a arreglos de los tipos primitivos. Collections también es una clase de utilidades, de métodos static que implementan algoritmos aplicados a todo tipo de colecciones.
Clase Arrays
Java 2 incorpora la clase Arrays para disponer de métodos que trabajen con arreglos de cualquier tipo. Estos métodos implementan algoritmos de búsqueda, ordenación y de asignación de un valor al array completo. Todos los métodos son static (métodos de clase). No se pueden crear objetos de la clase Arrays, el constructor que tiene es privado.
Ordenación de arrays
El método de ordenación, sort(), está sobrecargado, de tal forma que se puede ordenar un array de cualquier tipo primitivo y, en general, de tipo Object.sort() implementa el algoritmo de ordenación quicksort que asegura una eficiencia n log n.
Ejemplo
double []w = {12.4, 5.6, 3.5, -2.0, 6.0, -4.5, 22.0};
// Llamada a sort() para ordenar w
Arrays.sort(w);
A continuación se muestran algunos de los métodos de ordenación:
public static void sort(double []w);
public static void sort(int []w);
public static void sort(long []w);
public static void sort(Object []w);
public static void sort(Object []w, Comparator cmp);
Se pueden ordenar un subarray, para ello se especifica el índice inicio (inclusive) y final (exclusive):
// ordena los elementos w[inicio] . . w[final-1]
public static void sort(double []w, int inicio, int final);
public static void sort(int []w, int inicio, int final);
. . .
Norma
Para ordenar un arreglo de objetos los elementos deben implementar la interfaz Comparable ya que el criterio de ordenación está determinado por el método:
int compareTo(Object x);
Ejemplo
Declarar la clase Racional para representar un número racional (numerador, denominador) y llenar un array de objetos de esa clase. A continuación, ordenar de forma creciente el arreglo de números racionales.
La clase Racional tiene dos atributos de tipo int: numerador y denominador. Implementa la interfaz Comparable para poder realizar la ordenación con el método Arrays.sort(). Por ello es necesario definir el método int compareTo() de tal forma que devuelva -1, 0, 1 si el número racional primer operando (this) es menor, igual o mayor, respectivamente que el número racional pasado como argumento.
import java.util.*;
public class Racional implements Comparable {
private int numerador, denominador;
public Racional(int n, int d) throws Exception{
numerador = n;
denominador = d;
if(denominador == 0) throw new Exception(«Denominador 0»);
}
public String toString(){
return numerador + «/» + denominador;
}
@Override
public int compareTo(Object x) { // método de interfaz
Racional r;
r = (Racional) x;
if(valorReal()<r.valorReal())
return -1;
else if(valorReal()>r.valorReal())
return 1;
else
return 0;
}
private double valorReal(){
return (double)numerador/(double)denominador;
}
// . . .
}
import java.util.*;
// clase principal, crea los objetos de manera aleatoria,
// se escriben en pantalla, a continuación se ordena, y por
// último se vuelve escribir.
public class Ejemplo {
static int MR=7;
public static void main(String[] args) {
Racional []ar = new Racional[MR];
try{
// numerador y denominador se genera aleatoriamente
for(int i=0;i<MR;i++){
int n, d;
n = (int)(Math.random()*21+1);
d = (int)(Math.random()*21+1);
ar[i] = new Racional(n,d);
}
}catch(Exception e){;}
// listado de los objetos creados
System.out.println(«Lista de numeros racionales: «);
escribe(ar);
// ordenación del array
Arrays.sort(ar);
// listado de los objetos ordenados
System.out.println(«Lista ordenada de números racionales: «);
escribe(ar);
}
static void escribe(Racional []r){
for(int i=0;i<r.length;i++)
System.out.println(r[i] + «»);
System.out.println();
}
}
Búsqueda de una clave
La operación de búsqueda se realiza sobre un arreglo ordenado. La clase Arrays dispone del método static int bineraySearch() para realizar la búsqueda de un elemento en un arreglo. El método devuelve la posición del elemento en el array, o bien, si no está, -p, en el que p es la posición de inserción del elemento en el arreglo. El algoritmo que utiliza el método es el de búsqueda binaria que asegura una eficiencia de log n. El método está sobrecargado para cada tipo de dato primitivo, y para arrays de cualquier objeto (Object) que implemente la interfaz Comparable.
Ejemplo
int []w = {14, -5, 3, 2, 6, -4, 22, 4};
// llamada a sort() para ordenar w
Arrays.sort(w);
// búsqueda de un elemento
int k;
k = Arrays.binarySearch(w,4);
if(k>=0)
System.out.println(«Posición de » + 4 + » en la lista: » + k);
A continuación se escribe la declaración de alguno de estos métodos:
public static int binarySearch(double []w, double clave);
public static int binarySearch(int []w, int clave);
public static int binarySearch(Object []w, Object clave);
public static int binarySearch(Object []w, Object clave, Comparator c);
Asignación de un elemento
Otra utilidad de la clase Arrays es el método fill() para asignar un elemento a todas las posiciones de un array, o bien a un rango del arreglo. El método está sobrecargado, habiendo una declaración para cada tipo de dato primitivo y para Object. A continuación se escribe la declaración de fill() para algunos tipos:
public static void fill(int []w, int inicio, int final, int val);
public static void fill(Object []w, Object val);
. . .
Ejemplo
Definir un arreglo de enteros, inicializar la primera mitad a-1 y la segunda mitad a+1. Además, inicializar un arreglo de caracteres a la letra «a» y un arreglo de cadenas a «Paloma». Se definen arreglos de los tipos pedidos y de tamaño constante. Para inicializar la primera mitad del array a[] hay que especificar el índice inicio = 0 y final = a.length/2; la otra mitad tiene como inicio el anterior final.
static final int N=10;
int []iv = new int[N];
char[] cv = new char[N];
String []sv = new String[N];
// llenado de los arrays
Arrays.fill(iv,0,iv.length/2,-1);
Arrays.fill(iv,iv.length/2,-1);
Arrays.fill(cv,’a’);
Arrays.fill(sv,»Paloma»);
Clase Collections
Esta clase se encuentra en el paquete java.util; está diseñada para trabajar con colecciones: List, Map, Set, en general sobre cualquier Collection. Agrupa métodos static que implementan algoritmos genéricos de ordenación, búsqueda, máximo y mínimo. Además, dispone de métodos para dotar de la cualidad de sincronización a una colección, y para convertir una colección a «solo lectura».
Ordenación y búsqueda
Los métodos de ordenación se aplican a una lista cuyos elementos implementan la interfaz Comparable y que se puedan comparar mutuamente. También, hay una sobrecarga de estos métodos para realizar la comparación con la interfaz Comparator.
public static void sort(List lista);
public static void sort(List lista, Comparator cmp);
public static int binarySearch(List lista, Object clave);
public static int binarySearch(List lista, Object cl, Comparator cmp);
Máximo y mínimo
Los métodos max() y min() devuelven el máximo y mínimo, respectivamente, de una colección. Para que se pueda realizar la operación, todos los elementos deben implementar la interfaz Comparable y ser mutuamente comparables. Es decir, si por ejemplo una colección guarda números complejos y cadenas, difícilmente se podrá obtener el máximo (además de ser absurdo). Los métodos son los siguientes:
public static Object max(Collection c);
public static Object min(Collection c);
// sobrecarga que obtiene el máximo o mínimo respecto a un comparador
public static Object max(Collection c, Comparator cmp);
public static Object min(Collection c, Comparator cmp);
Sincronización
Para añadir la cualidad de sincronización a las colecciones, Collections dispone de métodos que se aplican a cada tipo de colección:
public static Map synchronizedMap(Map mapa);
public static Set synchronizedSet(Set cn);
Conversión a solo lectura
Estos métodos convierten la colección al modo solo lectura, de tal forma que la operación de añadir (add) o eliminar (remove) un elemento levanta la excepción UnsupportedOperationException. Algunos de los métodos son los siguientes:
public static List unmodifiableList(List lista);
public static Set unmodifiableSet(Set conjunto);
public static Collection unmodifiable Collection(Collection c);
Ejemplo
A continuación se escribe un ejemplo, en el que se crea un Set y después se convierte a modo solo lectura.
Set cn = new HashSet();
cn.add(«Marta»);
// crea una visión de cn no modificable, de solo lectura
cn = Collections.unmodifiableSet(cn);
Utilidades
La clase Collections dispone de métodos útiles para ciertos procesos algorítmicos. El método nCopies() crea una lista con n copias de un elemento; el método copy() crea una lista copia de otra; fill() llena todos los elementos de una lista con un objeto.
public static List nCopies(int n, Object ob);
public static void copy(List destino, List fuente);
public static void fill(List lista, Object ob);
El método reverse() invierte la posición de los elementos de una lista. Si la lista está en orden creciente, la llamada Collections.reverse(lista) deja a la lista en orden decreciente.
public static void reverse(List lista);
También incluye el método shuffle() para reordenar aleatoriamente los elementos de una lista.
public static void shuffle(List lista);
Ejemplo
Se realizan diversas operaciones utilizando métodos de la clase Collections: crear una lista a partir de la copia n veces de una cadena, ordenar una lista de objetos Integer, buscar el máximo, etcétera. Se escribe el método main() con las operaciones nCopies(), sort(), max(), min() y reverse(). La declaración de la lista de objetos especifica que el tipo de los elementos es Integer. De esa forma el compilador realiza comprobaciones de tipo. También se puede realizar de forma genérica: List lista = new ArrayList(); de tal forma que se podría añadir cualquier tipo de objeto.
public static void main(String[] args) {
int n=11;
List lista1;
// Crea una lista formada por n copias de «Marga»
lista1 = Collections.nCopies(n, «Marga»);
System.out.println(lista1);
// Crea una lista de objetos Integer, se ordena y se invierte
List<Integer> lista2 = new ArrayList<Integer>();
for(int i=1;i<=n;i++)
lista2.add(new Integer((int)(Math.random()*100+1)));
System.out.println(lista2);
System.out.println(«Máximo: » + Collections.max(lista2)
+ » \t Mínimo: » + Collections.min(lista2));
Collections.sort(lista2);
System.out.println(lista2);
Collections.reverse(lista2);
System.out.println(lista2);
}