二十二、数组(4)

本章概要

  • 随机生成
  • 泛型和基本数组

随机生成

我们可以按照 Count.java 的结构创建一个生成随机值的工具:

Rand.java

java 复制代码
import java.util.*;
import java.util.function.*;

import static com.example.test.ConvertTo.primitive;

public interface Rand {
    int MOD = 10_000;

    class Boolean implements Supplier<java.lang.Boolean> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Boolean get() {
            return r.nextBoolean();
        }

        public java.lang.Boolean get(int n) {
            return get();
        }

        public java.lang.Boolean[] array(int sz) {
            java.lang.Boolean[] result =
                    new java.lang.Boolean[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }

    class Pboolean {
        public boolean[] array(int sz) {
            return primitive(new Boolean().array(sz));
        }
    }

    class Byte
            implements Supplier<java.lang.Byte> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Byte get() {
            return (byte) r.nextInt(MOD);
        }

        public java.lang.Byte get(int n) {
            return get();
        }

        public java.lang.Byte[] array(int sz) {
            java.lang.Byte[] result =
                    new java.lang.Byte[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }

    class Pbyte {
        public byte[] array(int sz) {
            return primitive(new Byte().array(sz));
        }
    }

    class Character
            implements Supplier<java.lang.Character> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Character get() {
            return (char) r.nextInt('a', 'z' + 1);
        }

        public java.lang.Character get(int n) {
            return get();
        }

        public java.lang.Character[] array(int sz) {
            java.lang.Character[] result =
                    new java.lang.Character[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }

    class Pchar {
        public char[] array(int sz) {
            return primitive(new Character().array(sz));
        }
    }

    class Short
            implements Supplier<java.lang.Short> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Short get() {
            return (short) r.nextInt(MOD);
        }

        public java.lang.Short get(int n) {
            return get();
        }

        public java.lang.Short[] array(int sz) {
            java.lang.Short[] result =
                    new java.lang.Short[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }

    class Pshort {
        public short[] array(int sz) {
            return primitive(new Short().array(sz));
        }
    }

    class Integer
            implements Supplier<java.lang.Integer> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Integer get() {
            return r.nextInt(MOD);
        }

        public java.lang.Integer get(int n) {
            return get();
        }

        public java.lang.Integer[] array(int sz) {
            int[] primitive = new Pint().array(sz);
            java.lang.Integer[] result =
                    new java.lang.Integer[sz];
            for (int i = 0; i < sz; i++) {
                result[i] = primitive[i];
            }
            return result;
        }
    }

    class Pint implements IntSupplier {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public int getAsInt() {
            return r.nextInt(MOD);
        }

        public int get(int n) {
            return getAsInt();
        }

        public int[] array(int sz) {
            return r.ints(sz, 0, MOD).toArray();
        }
    }

    class Long implements Supplier<java.lang.Long> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Long get() {
            return r.nextLong(MOD);
        }

        public java.lang.Long get(int n) {
            return get();
        }

        public java.lang.Long[] array(int sz) {
            long[] primitive = new Plong().array(sz);
            java.lang.Long[] result =
                    new java.lang.Long[sz];
            for (int i = 0; i < sz; i++) {
                result[i] = primitive[i];
            }
            return result;
        }
    }

    class Plong implements LongSupplier {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public long getAsLong() {
            return r.nextLong(MOD);
        }

        public long get(int n) {
            return getAsLong();
        }

        public long[] array(int sz) {
            return r.longs(sz, 0, MOD).toArray();
        }
    }

    class Float
            implements Supplier<java.lang.Float> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Float get() {
            return (float) trim(r.nextDouble());
        }

        public java.lang.Float get(int n) {
            return get();
        }

        public java.lang.Float[] array(int sz) {
            java.lang.Float[] result =
                    new java.lang.Float[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }

    class Pfloat {
        public float[] array(int sz) {
            return primitive(new Float().array(sz));
        }
    }

    static double trim(double d) {
        return
                ((double) Math.round(d * 1000.0)) / 100.0;
    }

    class Double implements Supplier<java.lang.Double> {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public java.lang.Double get() {
            return trim(r.nextDouble());
        }

        public java.lang.Double get(int n) {
            return get();
        }

        public java.lang.Double[] array(int sz) {
            double[] primitive =
                    new Rand.Pdouble().array(sz);
            java.lang.Double[] result =
                    new java.lang.Double[sz];
            for (int i = 0; i < sz; i++) {
                result[i] = primitive[i];
            }
            return result;
        }
    }

    class Pdouble implements DoubleSupplier {
        SplittableRandom r = new SplittableRandom(47);

        @Override
        public double getAsDouble() {
            return trim(r.nextDouble());
        }

        public double get(int n) {
            return getAsDouble();
        }

        public double[] array(int sz) {
            double[] result = r.doubles(sz).toArray();
            Arrays.setAll(result,
                    n -> result[n] = trim(result[n]));
            return result;
        }
    }

    class String
            implements Supplier<java.lang.String> {
        SplittableRandom r = new SplittableRandom(47);
        private int strlen = 7; // Default length

        public String() {
        }

        public String(int strLength) {
            strlen = strLength;
        }

        @Override
        public java.lang.String get() {
            return r.ints(strlen, 'a', 'z' + 1)
                    .collect(StringBuilder::new,
                            StringBuilder::appendCodePoint,
                            StringBuilder::append).toString();
        }

        public java.lang.String get(int n) {
            return get();
        }

        public java.lang.String[] array(int sz) {
            java.lang.String[] result =
                    new java.lang.String[sz];
            Arrays.setAll(result, n -> get());
            return result;
        }
    }
}

ConvertTo.java

java 复制代码
public interface ConvertTo {
    static boolean[] primitive(Boolean[] in) {
        boolean[] result = new boolean[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i]; // Autounboxing
        }
        return result;
    }

    static char[] primitive(Character[] in) {
        char[] result = new char[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static byte[] primitive(Byte[] in) {
        byte[] result = new byte[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static short[] primitive(Short[] in) {
        short[] result = new short[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static int[] primitive(Integer[] in) {
        int[] result = new int[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static long[] primitive(Long[] in) {
        long[] result = new long[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static float[] primitive(Float[] in) {
        float[] result = new float[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static double[] primitive(Double[] in) {
        double[] result = new double[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    // Convert from primitive array to wrapped array:
    static Boolean[] boxed(boolean[] in) {
        Boolean[] result = new Boolean[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i]; // Autoboxing
        }
        return result;
    }

    static Character[] boxed(char[] in) {
        Character[] result = new Character[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Byte[] boxed(byte[] in) {
        Byte[] result = new Byte[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Short[] boxed(short[] in) {
        Short[] result = new Short[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Integer[] boxed(int[] in) {
        Integer[] result = new Integer[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Long[] boxed(long[] in) {
        Long[] result = new Long[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Float[] boxed(float[] in) {
        Float[] result = new Float[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }

    static Double[] boxed(double[] in) {
        Double[] result = new Double[in.length];
        for (int i = 0; i < in.length; i++) {
            result[i] = in[i];
        }
        return result;
    }
}

对于除了 intlongdouble 之外的所有基本类型元素生成器,只生成数组,而不是 Count 中看到的完整操作集。这只是一个设计选择,因为本书不需要额外的功能。

下面是对所有 Rand 工具的测试:

TestRand.java

java 复制代码
import java.util.*;
import java.util.stream.*;

import static com.example.test.ArrayShow.show;

public class TestRand {
    static final int SZ = 5;

    public static void main(String[] args) {
        System.out.println("Boolean");
        Boolean[] a1 = new Boolean[SZ];
        Arrays.setAll(a1, new Rand.Boolean()::get);
        show(a1);
        a1 = Stream.generate(new Rand.Boolean())
                .limit(SZ + 1).toArray(Boolean[]::new);
        show(a1);
        a1 = new Rand.Boolean().array(SZ + 2);
        show(a1);
        boolean[] a1b =
                new Rand.Pboolean().array(SZ + 3);
        show(a1b);

        System.out.println("Byte");
        Byte[] a2 = new Byte[SZ];
        Arrays.setAll(a2, new Rand.Byte()::get);
        show(a2);
        a2 = Stream.generate(new Rand.Byte())
                .limit(SZ + 1).toArray(Byte[]::new);
        show(a2);
        a2 = new Rand.Byte().array(SZ + 2);
        show(a2);
        byte[] a2b = new Rand.Pbyte().array(SZ + 3);
        show(a2b);

        System.out.println("Character");
        Character[] a3 = new Character[SZ];
        Arrays.setAll(a3, new Rand.Character()::get);
        show(a3);
        a3 = Stream.generate(new Rand.Character())
                .limit(SZ + 1).toArray(Character[]::new);
        show(a3);
        a3 = new Rand.Character().array(SZ + 2);
        show(a3);
        char[] a3b = new Rand.Pchar().array(SZ + 3);
        show(a3b);

        System.out.println("Short");
        Short[] a4 = new Short[SZ];
        Arrays.setAll(a4, new Rand.Short()::get);
        show(a4);
        a4 = Stream.generate(new Rand.Short())
                .limit(SZ + 1).toArray(Short[]::new);
        show(a4);
        a4 = new Rand.Short().array(SZ + 2);
        show(a4);
        short[] a4b = new Rand.Pshort().array(SZ + 3);
        show(a4b);

        System.out.println("Integer");
        int[] a5 = new int[SZ];
        Arrays.setAll(a5, new Rand.Integer()::get);
        show(a5);
        Integer[] a5b =
                Stream.generate(new Rand.Integer())
                        .limit(SZ + 1).toArray(Integer[]::new);
        show(a5b);
        a5b = new Rand.Integer().array(SZ + 2);
        show(a5b);
        a5 = IntStream.generate(new Rand.Pint())
                .limit(SZ + 1).toArray();
        show(a5);
        a5 = new Rand.Pint().array(SZ + 3);
        show(a5);

        System.out.println("Long");
        long[] a6 = new long[SZ];
        Arrays.setAll(a6, new Rand.Long()::get);
        show(a6);
        Long[] a6b = Stream.generate(new Rand.Long())
                .limit(SZ + 1).toArray(Long[]::new);
        show(a6b);
        a6b = new Rand.Long().array(SZ + 2);
        show(a6b);
        a6 = LongStream.generate(new Rand.Plong())
                .limit(SZ + 1).toArray();
        show(a6);
        a6 = new Rand.Plong().array(SZ + 3);
        show(a6);

        System.out.println("Float");
        Float[] a7 = new Float[SZ];
        Arrays.setAll(a7, new Rand.Float()::get);
        show(a7);
        a7 = Stream.generate(new Rand.Float())
                .limit(SZ + 1).toArray(Float[]::new);
        show(a7);
        a7 = new Rand.Float().array(SZ + 2);
        show(a7);
        float[] a7b = new Rand.Pfloat().array(SZ + 3);
        show(a7b);

        System.out.println("Double");
        double[] a8 = new double[SZ];
        Arrays.setAll(a8, new Rand.Double()::get);
        show(a8);
        Double[] a8b =
                Stream.generate(new Rand.Double())
                        .limit(SZ + 1).toArray(Double[]::new);
        show(a8b);
        a8b = new Rand.Double().array(SZ + 2);
        show(a8b);
        a8 = DoubleStream.generate(new Rand.Pdouble())
                .limit(SZ + 1).toArray();
        show(a8);
        a8 = new Rand.Pdouble().array(SZ + 3);
        show(a8);

        System.out.println("String");
        String[] s = new String[SZ - 1];
        Arrays.setAll(s, new Rand.String()::get);
        show(s);
        s = Stream.generate(new Rand.String())
                .limit(SZ).toArray(String[]::new);
        show(s);
        s = new Rand.String().array(SZ + 1);
        show(s);

        Arrays.setAll(s, new Rand.String(4)::get);
        show(s);
        s = Stream.generate(new Rand.String(4))
                .limit(SZ).toArray(String[]::new);
        show(s);
        s = new Rand.String(4).array(SZ + 1);
        show(s);
    }
}

ArrayShow.java

java 复制代码
import java.util.*;

public interface ArrayShow {
    static void show(Object[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(boolean[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(byte[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(char[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(short[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(int[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(long[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(float[] a) {
        System.out.println(Arrays.toString(a));
    }

    static void show(double[] a) {
        System.out.println(Arrays.toString(a));
    }

    // Start with a description:
    static void show(String info, Object[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, boolean[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, byte[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, char[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, short[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, int[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, long[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, float[] a) {
        System.out.print(info + ": ");
        show(a);
    }

    static void show(String info, double[] a) {
        System.out.print(info + ": ");
        show(a);
    }
}

注意(除了 String 部分之外),这段代码与 TestCount.java 中的代码相同,CountRand 替换。

泛型和基本数组

在本章的前面,我们被提醒,泛型不能和基元一起工作。在这种情况下,我们必须从基元数组转换为包装类型的数组,并且还必须从另一个方向转换。ConvertTo.java是一个转换器可以同时对所有类型的数据执行操作。

primitive() 的每个版本都创建一个准确长度的适当基元数组,然后从包装类的 in 数组中复制元素。如果任何包装的数组元素是 null ,你将得到一个异常(这是合理的---否则无法选择有意义的值进行替换)。注意在这个任务中自动装箱如何发生。

下面是对 ConvertTo 中所有方法的测试:

java 复制代码
import java.util.*;

import static com.example.test.ArrayShow.show;
import static com.example.test.ConvertTo.boxed;
import static com.example.test.ConvertTo.primitive;

public class TestConvertTo {
    static final int SIZE = 6;

    public static void main(String[] args) {
        Boolean[] a1 = new Boolean[SIZE];
        Arrays.setAll(a1, new Rand.Boolean()::get);
        boolean[] a1p = primitive(a1);
        show("a1p", a1p);
        Boolean[] a1b = boxed(a1p);
        show("a1b", a1b);

        Byte[] a2 = new Byte[SIZE];
        Arrays.setAll(a2, new Rand.Byte()::get);
        byte[] a2p = primitive(a2);
        show("a2p", a2p);
        Byte[] a2b = boxed(a2p);
        show("a2b", a2b);

        Character[] a3 = new Character[SIZE];
        Arrays.setAll(a3, new Rand.Character()::get);
        char[] a3p = primitive(a3);
        show("a3p", a3p);
        Character[] a3b = boxed(a3p);
        show("a3b", a3b);

        Short[] a4 = new Short[SIZE];
        Arrays.setAll(a4, new Rand.Short()::get);
        short[] a4p = primitive(a4);
        show("a4p", a4p);
        Short[] a4b = boxed(a4p);
        show("a4b", a4b);

        Integer[] a5 = new Integer[SIZE];
        Arrays.setAll(a5, new Rand.Integer()::get);
        int[] a5p = primitive(a5);
        show("a5p", a5p);
        Integer[] a5b = boxed(a5p);
        show("a5b", a5b);

        Long[] a6 = new Long[SIZE];
        Arrays.setAll(a6, new Rand.Long()::get);
        long[] a6p = primitive(a6);
        show("a6p", a6p);
        Long[] a6b = boxed(a6p);
        show("a6b", a6b);

        Float[] a7 = new Float[SIZE];
        Arrays.setAll(a7, new Rand.Float()::get);
        float[] a7p = primitive(a7);
        show("a7p", a7p);
        Float[] a7b = boxed(a7p);
        show("a7b", a7b);

        Double[] a8 = new Double[SIZE];
        Arrays.setAll(a8, new Rand.Double()::get);
        double[] a8p = primitive(a8);
        show("a8p", a8p);
        Double[] a8b = boxed(a8p);
        show("a8b", a8b);
    }
}

在每种情况下,原始数组都是为包装类型创建的,并使用 Arrays.setAll() 填充,正如我们在 TestCouner.java 中所做的那样(这也验证了 Arrays.setAll() 是否能同 IntegerLong ,和 Double )。然后 ConvertTo.primitive() 将包装器数组转换为对应的基元数组,ConverTo.boxed() 将其转换回来。

相关推荐
dzweather10 个月前
构造分钟降水J文件
c#·随机生成·j文件·分钟降水