Класс Arrays
В java.util вы найдете класс Arrays, который содержит набор статических методов, выполняющих вспомогательные функции для массивов. Среди них четыре основных функции: equals( ) - для сравнения двух массивов на равенство; fill( ) - для заполнения массива значением; sort( ) - для сортировки массива; и binarySearch( ) - для нахождения элемента в отсортированном массиве. Все эти методы перегружены для всех примитивных типов и для типа Object. Кроме того, есть одиночный метод asList( ), который получает массив и переводит его в контейнер List, который вы выучите позже в этой главе.
Являясь полезным, класс Arrays остается маленьким, вобрав в себя всю функциональность. Например, было бы здорово иметь возможность легко печатать элементы массива, не вводя код цикла for всякий раз. И, как вы увидите, метод fill( ) получает только одно значение и помещает его в массив, так что, если вы хотите, например, заполнить массив случайными числами, fill( ) - не помощник.
Так что есть смысл пополнить класс Arrays дополнительными утилитами, которые будут по соглашению помешены в package com.bruceeckel.util. Здесь будет печать массива любого типа и заполнения массива значениями или объектами, которые создаются объектом, называемым генератор, который определите вы.
Поскольку необходим код для создания каждого примитивного типа наряду с Object, будет много сильно похожего кода [46]. Например, интерфейс “генератор” требуется для каждого типа, потому что возвращаемый тип next( ) должен быть различным в каждом случае:
//: com:bruceeckel:util:Generator.java
package com.bruceeckel.util; public interface Generator { Object next(); } ///:~
//: com:bruceeckel:util:BooleanGenerator.java
package com.bruceeckel.util; public interface BooleanGenerator { boolean next(); } ///:~
//: com:bruceeckel:util:ByteGenerator.java
package com.bruceeckel.util; public interface ByteGenerator { byte next(); } ///:~
//: com:bruceeckel:util:CharGenerator.java
package com.bruceeckel.util; public interface CharGenerator { char next(); } ///:~
//: com:bruceeckel:util:ShortGenerator.java
package com.bruceeckel.util; public interface ShortGenerator { short next(); } ///:~
//: com:bruceeckel:util:IntGenerator.java
package com.bruceeckel.util; public interface IntGenerator { int next(); } ///:~
//: com:bruceeckel:util:LongGenerator.java
package com.bruceeckel.util; public interface LongGenerator { long next(); } ///:~
//: com:bruceeckel:util:FloatGenerator.java
package com.bruceeckel.util; public interface FloatGenerator { float next(); } ///:~
//: com:bruceeckel:util:DoubleGenerator.java
package com.bruceeckel.util; public interface DoubleGenerator { double next(); } ///:~
Arrays2 содержит варианты функций print( ), перегруженной для каждого типа. Вы можете просто напечатать массив, вы можете добавить сообщение перед печатью массива или вы можете напечатать пределы элементов массива. Код метода print( ) говорит сам за себя:
//: com:bruceeckel:util:Arrays2.java
// Дополнение к java.util.Arrays, для обеспечения
// дополнительной полезной функциональности при работе
// с массивами. Позволяет печатать массивы,
// и заполнять их определенными пользователем
// "генераторами" объектов.
package com.bruceeckel.util; import java.util.*;
public class Arrays2 { private static void
start(int from, int to, int length) { if(from != 0 || to != length) System.out.print("["+ from +":"+ to +"] "); System.out.print("("); } private static void end() { System.out.println(")"); } public static void print(Object[] a) { print(a, 0, a.length); } public static void print(String msg, Object[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(Object[] a, int from, int to){ start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to -1) System.out.print(", "); } end(); } public static void print(boolean[] a) { print(a, 0, a.length); } public static void print(String msg, boolean[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(boolean[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to -1) System.out.print(", "); } end(); } public static void print(byte[] a) { print(a, 0, a.length); } public static void print(String msg, byte[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(byte[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to -1) System.out.print(", "); } end(); } public static void print(char[] a) { print(a, 0, a.length); } public static void print(String msg, char[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(char[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to -1) System.out.print(", "); } end(); } public static void print(short[] a) { print(a, 0, a.length); } public static void print(String msg, short[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(short[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to - 1) System.out.print(", "); } end(); } public static void print(int[] a) { print(a, 0, a.length); } public static void print(String msg, int[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(int[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to - 1) System.out.print(", "); } end(); } public static void print(long[] a) { print(a, 0, a.length); } public static void print(String msg, long[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(long[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to - 1) System.out.print(", "); } end(); } public static void print(float[] a) { print(a, 0, a.length); } public static void print(String msg, float[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(float[] a, int from, int to) { start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to - 1) System.out.print(", "); } end(); } public static void print(double[] a) { print(a, 0, a.length); } public static void print(String msg, double[] a) { System.out.print(msg + " "); print(a, 0, a.length); } public static void print(double[] a, int from, int to){ start(from, to, a.length); for(int i = from; i < to; i++) { System.out.print(a[i]); if(i < to - 1) System.out.print(", "); } end(); } // Заполнение массива с использованием генератора:
public static void fill(Object[] a, Generator gen) { fill(a, 0, a.length, gen); } public static void fill(Object[] a, int from, int to, Generator gen){ for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(boolean[] a, BooleanGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(boolean[] a, int from, int to, BooleanGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(byte[] a, ByteGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(byte[] a, int from, int to, ByteGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(char[] a, CharGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(char[] a, int from, int to, CharGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(short[] a, ShortGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(short[] a, int from, int to, ShortGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(int[] a, IntGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(int[] a, int from, int to, IntGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(long[] a, LongGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(long[] a, int from, int to, LongGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(float[] a, FloatGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(float[] a, int from, int to, FloatGenerator gen) { for(int i = from; i < to; i++) a[i] = gen.next(); } public static void fill(double[] a, DoubleGenerator gen) { fill(a, 0, a.length, gen); } public static void fill(double[] a, int from, int to, DoubleGenerator gen){ for(int i = from; i < to; i++) a[i] = gen.next(); } private static Random r = new Random(); public static class RandBooleanGenerator implements BooleanGenerator { public boolean next() { return r.nextBoolean(); } } public static class RandByteGenerator implements ByteGenerator { public byte next() { return (byte)r.nextInt(); } } static String ssource = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; static char[] src = ssource.toCharArray(); public static class RandCharGenerator implements CharGenerator { public char next() { int pos = Math.abs(r.nextInt()); return src[pos % src.length]; } } public static class RandStringGenerator implements Generator { private int len; private RandCharGenerator cg = new RandCharGenerator(); public RandStringGenerator(int length) { len = length; } public Object next() { char[] buf = new char[len]; for(int i = 0; i < len; i++) buf[i] = cg.next(); return new String(buf); } } public static class RandShortGenerator implements ShortGenerator { public short next() { return (short)r.nextInt(); } } public static class RandIntGenerator implements IntGenerator { private int mod = 10000; public RandIntGenerator() {} public RandIntGenerator(int modulo) { mod = modulo; } public int next() { return r.nextInt() % mod; } } public static class RandLongGenerator implements LongGenerator { public long next() { return r.nextLong(); } } public static class RandFloatGenerator implements FloatGenerator { public float next() { return r.nextFloat(); } } public static class RandDoubleGenerator implements DoubleGenerator { public double next() {return r.nextDouble();} } } ///:~
Для заполнения массива с использованием генератора метод fill( ) получает ссылку на подходящий interface генератора, который имеет метод next( ), который каким- то образом производит объект правильного типа (в зависимости от того, как реализован интерфейс). Метод fill( ) просто вызывает next( ) до тех пор, пока не будут достигнуты нужные пределы для заполнения. Теперь вы можете создать любой генератор, реализовав подходящий interface, и использовать ваш генератор с методом fill( ).
Случайные генераторы данных полезны для тестирования, так что набор внутренних классов создается для реализации всех интерфейсов примитивных генераторов, так же как и генератор String, представляющий Object. Вы можете видеть, что RandStringGenerator использует RandCharGenerator для заполнения массива символов, который затем переводится в String. Размер массива определяется по аргументу конструктора.
Для генерации не слишком больших чисел RandIntGenerator берет по умолчанию остаток от деления на 10,000, но перегрузка конструктора позволит вам выбрать меньшее значение.
Вот программа для проверки библиотеки и демонстрации ее использования:
//: c09:TestArrays2.java
// Проверки и демонстрация утилит Arrays2
import com.bruceeckel.util.*;
public class TestArrays2 { public static void main(String[] args) { int size = 6; // Или получим size из командной строки:
if(args.length != 0) size = Integer.parseInt(args[0]); boolean[] a1 = new boolean[size]; byte[] a2 = new byte[size]; char[] a3 = new char[size]; short[] a4 = new short[size]; int[] a5 = new int[size]; long[] a6 = new long[size]; float[] a7 = new float[size]; double[] a8 = new double[size]; String[] a9 = new String[size]; Arrays2.fill(a1, new Arrays2.RandBooleanGenerator()); Arrays2.print(a1); Arrays2.print("a1 = ", a1); Arrays2.print(a1, size/3, size/3 + size/3); Arrays2.fill(a2, new Arrays2.RandByteGenerator()); Arrays2.print(a2); Arrays2.print("a2 = ", a2); Arrays2.print(a2, size/3, size/3 + size/3); Arrays2.fill(a3, new Arrays2.RandCharGenerator()); Arrays2.print(a3); Arrays2.print("a3 = ", a3); Arrays2.print(a3, size/3, size/3 + size/3); Arrays2.fill(a4, new Arrays2.RandShortGenerator()); Arrays2.print(a4); Arrays2.print("a4 = ", a4); Arrays2.print(a4, size/3, size/3 + size/3); Arrays2.fill(a5, new Arrays2.RandIntGenerator()); Arrays2.print(a5); Arrays2.print("a5 = ", a5); Arrays2.print(a5, size/3, size/3 + size/3); Arrays2.fill(a6, new Arrays2.RandLongGenerator()); Arrays2.print(a6); Arrays2.print("a6 = ", a6); Arrays2.print(a6, size/3, size/3 + size/3); Arrays2.fill(a7, new Arrays2.RandFloatGenerator()); Arrays2.print(a7); Arrays2.print("a7 = ", a7); Arrays2.print(a7, size/3, size/3 + size/3); Arrays2.fill(a8, new Arrays2.RandDoubleGenerator()); Arrays2.print(a8); Arrays2.print("a8 = ", a8); Arrays2.print(a8, size/3, size/3 + size/3); Arrays2.fill(a9, new Arrays2.RandStringGenerator(7)); Arrays2.print(a9); Arrays2.print("a9 = ", a9); Arrays2.print(a9, size/3, size/3 + size/3); } } ///:~
Параметр size имеет значение по умолчанию, но вы можете также установить его из командной строки.