Не смотря на свою полезность, класс Arrays с недоделанной функциональностью. Например, было бы прекрасно иметь возможность легкой распечатки элементов массива без дополнительного регулярного ручного кодирования циклов loop. И как вы увидите, метод fill( ) просто принимает единственное значение и помещает его в массив, так что если вы хотите, например, заполнить массив случайно сгенерированными числами, метод filд( ) не поможет.
Таким образом, имеет смысл дополнить класс Arrays некоторыми дополнительными утилитами, которые будут помещены в пакет com.bruceeckel.util для удобства. В ней распечатывается массив любого типа и заполняется массив значениями или объектами, которые создаются генератором, который вы определяете.
Поскольку код должен быть создан для каждого примитивного типа так же как и для Object, то здесь будет много дублирующего кода. [14] Например, интерфейс "генератора" требуется для каждого типа, поскольку возвращаемый тип метода next( ) должен отличатся в каждом случае:
package com.bruceeckel.util;
//: com:bruceeckel:util:Generator.java
public interface Generator { Object next(); } // /:~
// : com:bruceeckel:util:BooleanGenerator.java
public interface BooleanGenerator { boolean next(); } // /:~
// : com:bruceeckel:util:ByteGenerator.java
public interface ByteGenerator { byte next(); } // /:~
// : com:bruceeckel:util:CharGenerator.java
public interface CharGenerator { char next(); } // /:~
// : com:bruceeckel:util:ShortGenerator.java
public interface ShortGenerator { short next(); } // /:~
// : com:bruceeckel:util:IntGenerator.java
public interface IntGenerator { int next(); } // /:~
// : com:bruceeckel:util:LongGenerator.java
public interface LongGenerator { long next(); } // /:~
// : com:bruceeckel:util:FloatGenerator.java
public interface FloatGenerator { float next(); } // /:~
// : com:bruceeckel:util:DoubleGenerator.java
public interface DoubleGenerator { double next(); } // /:~
Arrays2 содержит вариант метода toString( ), перегруженный для каждого типа. Эти методы позволяют вам легко распечатать массыв. Код toString( ) вводит использование объекта StringBuffer вместо String. Это уклон в сторону эффективности. Когда вы собираете строку в методе, которая может вызываться очень много раз, благоразумнее использовать более эффективный класс StringBuffer вместо более последовательных операций класса String. В этом примере StringBuffer создается с начальным значением, а String используются для добавления. В итоге, result приводится к типу String, так как это возвращаемое значение:
//: com:bruceeckel:util:Arrays2.java
// A supplement to java.util.Arrays, to provide additional
// useful functionality when working with arrays. Allows
// any array to be converted to a String, and to be filled
// via a user-defined "generator" object.
package com.bruceeckel.util;
import java.util.*;
public class Arrays2 {
public static String toString(boolean[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(byte[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(char[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(short[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(int[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(long[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(float[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
public static String toString(double[] a) {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < a.length; i++) {
result.append(a[i]);
if (i < a.length - 1)
result.append(", ");
}
result.append("]");
return result.toString();
}
// Fill an array using a generator:
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();
}
}
private static String ssource = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static char[] src = ssource.toCharArray();
public static class RandCharGenerator implements CharGenerator {
public char next() {
return src[r.nextInt(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( ) принимает ссылку на соответствующий интерфейс генератора, в котором есть метод next( ), который каким-то образом воспроизводит объект правильного типа (в зависимости от того, какой интерфейс реализован). Метод fill( ) просто вызывает метод next( ) до тех пор, пока необходимый диапазон не будет заполнен. Теперь вы можете создать любой генератор путем реализации соответствующего интерфейса и использовать генератор в методе fill( ).
Генераторы случайных чисел полезны при тестировании, так что набор внутренних классов, созданных для реализации всех интерфейсов примитивных генераторов наряду с генератором для типа String, представляющего Object. Вы можете видеть, что RandStringGenerator использует RandCharGenerator для заполнения массива символов, которые затем превращаются в Striung. Размер массива определяется аргументом конструктора.
Для генерации чисел, которые не являются большими числами, RandIntGenerator берет остаток от деления на 10 000, но перегруженный конструктор позволяет вам выбирать меньшие значения.
[1] Эта издевательская ссылка связана с событиями в Китае после смерти Мао-Дзе Дуна, когда четыре человека, включая вдову Мао, сделали игру с властью и были демонизированы Китайской Коммунистической Партией под этим именем.
[3] Предупреждаем: пример из C++.
[4] Бесплатная публикация по email. Смотрите www.BruceEckel.com, чтобы подписаться.
[5] Получено по email от Kevlin Henney.
[6] Shalloway, Design Patterns Explained, and Alexandrescu, Advanced C++ Design (??)
[7] В языке Python все функции уже являются объектами, поэтому шаблон Команды часто является избыточным.
[9] Оригинальная версия была названа JPython, но проект изменился и имя было изменено для явного указания отличия новой версии.
[10] Измените установку в регистре python.security.respectJavaAccessibility = true в false, чтобы сделать тестирование более мощным, поскольку это позволит вам тестировать скрипт с использованием *всех* методов, даже приватных и пакетного уровня доступа.
[11] Ни одна мышь не погибла при создании этого примера.
[13] Это решения создано Jaroslav Tulach в дизайне проектирования, который я давал в Праге.
[14] Программисты на C++ заметят, как много кода может быть сжато при использовании аргументов по умолчанию и шаблонов. Программисты на Python заметят, что вся эта библиотека будет громоздкой и ненужной в этом языке.
← | Расширение Ant |