zoukankan      html  css  js  c++  java
  • Java基础之十六 数组

    数组:可以创建并组装它们,通过使用整型索引值访问它们的元素,并且它们的尺寸不能改变。

    16.1 数组为什么特殊

    数组与其他种类的容器之间的区别有三方面:效率,类型和保存基本类型的能力。
    数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速。但是为这种速度所付出的代价是数组对象的大小固定,并且在其生命周期中不可改变。
    ArrayList:它可以通过一个新实例,然后把旧实例中所有引用移到新实例中,从而实现更多空间的自动分配。但它的效率比数组低很多。
    数组可以持有基本类型,而泛型之前的容器不能。但有了泛型,容器旧可以指定并检查它们所持有对象的类型,并且有了自动包装机制,容器看起来还能够持有基本类型。
    数组和泛型容器比较:

    import java.util.*;
    import static net.mindview.util.Print.*;
    
    class BerylliumSphere {
      private static long counter;
      private final long id = counter++;
      public String toString() { return "Sphere " + id; }
    }
    public class ContainerComparison {
      public static void main(String[] args) {
        BerylliumSphere[] spheres = new BerylliumSphere[10];
        for(int i = 0; i < 5; i++)
          spheres[i] = new BerylliumSphere();
        print(Arrays.toString(spheres));
        print(spheres[4]);
    
        List<BerylliumSphere> sphereList =
          new ArrayList<BerylliumSphere>();
        for(int i = 0; i < 5; i++)
          sphereList.add(new BerylliumSphere());
        print(sphereList);
        print(sphereList.get(4));
    
        int[] integers = { 0, 1, 2, 3, 4, 5 };
        print(Arrays.toString(integers));
        print(integers[4]);
        
        List<Integer> intList = new ArrayList<Integer>(
          Arrays.asList(0, 1, 2, 3, 4, 5));
        intList.add(97);
        print(intList);
        print(intList.get(4));
      }
    } /* Output:
    [Sphere 0, Sphere 1, Sphere 2, Sphere 3, Sphere 4, null, null, null, null, null]
    Sphere 4
    [Sphere 5, Sphere 6, Sphere 7, Sphere 8, Sphere 9]
    Sphere 9
    [0, 1, 2, 3, 4, 5]
    4
    [0, 1, 2, 3, 4, 5, 97]
    4
    *///:~
    

    数组的优点是效率。

    16.2 数组是第一级对象

    无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建的一个真实对象,这个对象用以保存指向其他对象的引用。
    对象数组和基本类型数组在使用上几乎是相同的。唯一区别就是对象数组保存的是引用,基本类型数组直接保存基本类型的值。

    import java.util.*;
    import static net.mindview.util.Print.*;
    
    public class ArrayOptions {
      public static void main(String[] args) {
        // Arrays of objects:
        BerylliumSphere[] a; // Local uninitialized variable
        BerylliumSphere[] b = new BerylliumSphere[5];
        // The references inside the array are
        // automatically initialized to null:
        print("b: " + Arrays.toString(b));
        BerylliumSphere[] c = new BerylliumSphere[4];
        for(int i = 0; i < c.length; i++)
          if(c[i] == null) // Can test for null reference
            c[i] = new BerylliumSphere();
        // Aggregate initialization:
        BerylliumSphere[] d = { new BerylliumSphere(),
          new BerylliumSphere(), new BerylliumSphere()
        };
        print("d"+Arrays.toString(d));
        // Dynamic aggregate initialization:
        a = new BerylliumSphere[]{
          new BerylliumSphere(), new BerylliumSphere(),
        };
        // (Trailing comma is optional in both cases)
        print("a.length = " + a.length);
        print("b.length = " + b.length);
        print("c.length = " + c.length);
        print("d.length = " + d.length);
        a = d;
        print("a.length = " + a.length);
    
        // Arrays of primitives:
        int[] e; // Null reference
        int[] f = new int[5];
        // The primitives inside the array are
        // automatically initialized to zero:
        print("f: " + Arrays.toString(f));
        int[] g = new int[4];
        for(int i = 0; i < g.length; i++)
          g[i] = i*i;
        int[] h = { 11, 47, 93 };
        // Compile error: variable e not initialized:
        //!print("e.length = " + e.length);
        print("f.length = " + f.length);
        print("g.length = " + g.length);
        print("h.length = " + h.length);
        e = h;
        print("e.length = " + e.length);
        e = new int[]{ 1, 2 };
        print("e.length = " + e.length);
      }
    } /* Output:
    b: [null, null, null, null, null]
    a.length = 2
    b.length = 5
    c.length = 4
    d.length = 3
    a.length = 3
    f: [0, 0, 0, 0, 0]
    f.length = 5
    g.length = 4
    h.length = 3
    e.length = 3
    e.length = 2
    *///:~
    

    16.3 返回一个数组

    数组的清理由垃圾回收机制负责。

    import java.util.*;
    
    public class IceCream {
      private static Random rand = new Random(47);
      static final String[] FLAVORS = {
        "Chocolate", "Strawberry", "Vanilla Fudge Swirl",
        "Mint Chip", "Mocha Almond Fudge", "Rum Raisin",
        "Praline Cream", "Mud Pie"
      };
      public static String[] flavorSet(int n) {
        if(n > FLAVORS.length)
          throw new IllegalArgumentException("Set too big");
        String[] results = new String[n];
        boolean[] picked = new boolean[FLAVORS.length];
        for(int i = 0; i < n; i++) {
          int t;
          do
            t = rand.nextInt(FLAVORS.length);
          while(picked[t]);
          results[i] = FLAVORS[t];
          picked[t] = true;
        }
        return results;
      }
      public static void main(String[] args) {
        for(int i = 0; i < 7; i++)
          System.out.println(Arrays.toString(flavorSet(3)));
      }
    } /* Output:
    [Rum Raisin, Mint Chip, Mocha Almond Fudge]
    [Chocolate, Strawberry, Mocha Almond Fudge]
    [Strawberry, Mint Chip, Mocha Almond Fudge]
    [Rum Raisin, Vanilla Fudge Swirl, Mud Pie]
    [Vanilla Fudge Swirl, Chocolate, Mocha Almond Fudge]
    [Praline Cream, Strawberry, Mocha Almond Fudge]
    [Mocha Almond Fudge, Strawberry, Mint Chip]
    *///:~
    

    16.4 多维数组

    对于基本类型得多维数组,可以通过使用花括号将每个向量隔开:

    import java.util.*;
    
    public class MultidimensionalPrimitiveArray {
      public static void main(String[] args) {
        int[][] a = {
          { 1, 2, 3, },
          { 4, 5, 6, },
        };System.out.println(Arrays.deepToString(a));
        System.out.println(a[0].length);
        System.out.println(a[1].length);
      }
    } /* Output:
    [[1, 2, 3], [4, 5, 6]]
    *///:~
    

    还可以使用new来分配数组:

    import java.util.*;
    
    public class ThreeDWithNew {
      public static void main(String[] args) {
        // 3-D array with fixed length:
        int[][][] a = new int[2][2][4];
        System.out.println(Arrays.deepToString(a));
      }
    } /* Output:
    [[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
    *///:~
    

    你可以看到基本类型数组得值在不进行显式初始化得情况下,会被自动初始化。对象数组会被初始化为null。
    数组中构成矩阵得每个向量都可以具有任意得长度(粗糙数组)

    import java.util.*;
    
    public class RaggedArray {
      public static void main(String[] args) {
        Random rand = new Random(47);
        // 3-D array with varied-length vectors:
        int[][][] a = new int[rand.nextInt(7)][][];
        for(int i = 0; i < a.length; i++) {
          a[i] = new int[rand.nextInt(5)][];
          for(int j = 0; j < a[i].length; j++)
            a[i][j] = new int[rand.nextInt(5)];
        }
        System.out.println(Arrays.deepToString(a));
      }
    } /* Output:
    [[], [[0], [0], [0, 0, 0, 0]], [[], [0, 0], [0, 0]], [[0, 0, 0], [0], [0, 0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0], []], [[0], [], [0]]]
    *///:~
    

    用花括号把多个new表达式组织到一起:

    import java.util.*;
    
    public class MultidimensionalObjectArrays {
      public static void main(String[] args) {
        BerylliumSphere[][] spheres = {
          { new BerylliumSphere(), new BerylliumSphere() },
          { new BerylliumSphere(), new BerylliumSphere(),
            new BerylliumSphere(), new BerylliumSphere() },
          { new BerylliumSphere(), new BerylliumSphere(),
            new BerylliumSphere(), new BerylliumSphere(),
            new BerylliumSphere(), new BerylliumSphere(),
            new BerylliumSphere(), new BerylliumSphere() },
        };
        System.out.println(Arrays.deepToString(spheres));
      }
    } /* Output:
    [[Sphere 0, Sphere 1], [Sphere 2, Sphere 3, Sphere 4, Sphere 5], [Sphere 6, Sphere 7, Sphere 8, Sphere 9, Sphere 10, Sphere 11, Sphere 12, Sphere 13]]
    *///:~
    

    自动包装机制对数组初始化器也起作用:

    import java.util.*;
    
    public class AutoboxingArrays {
      public static void main(String[] args) {
        Integer[][] a = { // Autoboxing:
          { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
          { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
          { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 },
          { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 },
        };
        System.out.println(Arrays.deepToString(a));
      }
    } /* Output:
    [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80]]
    *///:~
    

    Arrays.deepToString()方法对基本类型数组和对象数组都起作用:

    import java.util.*;
    
    public class MultiDimWrapperArray {
      public static void main(String[] args) {
        Integer[][] a1 = { // Autoboxing
          { 1, 2, 3, },
          { 4, 5, 6, },
        };
        Double[][][] a2 = { // Autoboxing
          { { 1.1, 2.2 }, { 3.3, 4.4 } },
          { { 5.5, 6.6 }, { 7.7, 8.8 } },
          { { 9.9, 1.2 }, { 2.3, 3.4 } },
        };
        String[][] a3 = {
          { "The", "Quick", "Sly", "Fox" },
          { "Jumped", "Over" },
          { "The", "Lazy", "Brown", "Dog", "and", "friend" },
        };
        String[][] a4=new String[2][3];
        System.out.println("a1: " + Arrays.deepToString(a1));
        System.out.println("a2: " + Arrays.deepToString(a2));
        System.out.println("a3: " + Arrays.deepToString(a3));
        System.out.println("a3: " + Arrays.deepToString(a4));
      }
    } /* Output:
    a1: [[1, 2, 3], [4, 5, 6]]
    a2: [[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7, 8.8]], [[9.9, 1.2], [2.3, 3.4]]]
    a3: [[The, Quick, Sly, Fox], [Jumped, Over], [The, Lazy, Brown, Dog, and, friend]]
    *///:~
    

    16.5 数组与泛型

    数组与泛型不能很好的结合。你不能实例化具有参数化类型的数组。
    擦除会移除参数类型信息,而数组必须知道它们所持有的确切类型,以强制保证类型安全。
    参数化数组本身的类型:

    class ClassParameter<T> {
      public T[] f(T[] arg) { return arg; }
    }
    class MethodParameter {
      public static <T> T[] f(T[] arg) { return arg; }
    }
    public class ParameterizedArrayType {
      public static void main(String[] args) {
        Integer[] ints = { 1, 2, 3, 4, 5 };
        Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
        Integer[] ints2 =
          new ClassParameter<Integer>().f(ints);
        Double[] doubles2 =
          new ClassParameter<Double>().f(doubles);
        ints2 = MethodParameter.f(ints);
        doubles2 = MethodParameter.f(doubles);
      }
    } ///:~
    

    不能创建实际的持有泛型的数组对象,但是你可以创建非泛型的数组,然后将其转型:

    import java.util.*;
    
    public class ArrayOfGenerics {
      @SuppressWarnings("unchecked")
      public static void main(String[] args) {
        List<String>[] ls;
        List[] la = new List[10];
        ls = (List<String>[])la; // "Unchecked" warning
        ls[0] = new ArrayList<String>();
        // Compile-time checking produces an error:
        //ls[1] = new ArrayList<Integer>();
    
        // The problem: List<String> is a subtype of Object
        Object[] objects = ls; // So assignment is OK
        // Compiles and runs without complaint:
        objects[1] = new ArrayList<Integer>();
    
        // However, if your needs are straightforward it is
        // possible to create an array of generics, albeit
        // with an "unchecked" warning:
        List<BerylliumSphere>[] spheres =
          (List<BerylliumSphere>[])new List[10];
        for(int i = 0; i < spheres.length; i++)
          spheres[i] = new ArrayList<BerylliumSphere>();
      }
    } ///:~
    

    泛型在类或方法的边界处很有效,而在类或方法的内部,擦除通常会使泛型变得不适用。
    不能创建泛型数组:

    public class ArrayOfGenericType<T> {
      T[] array; // OK
      @SuppressWarnings("unchecked")
      public ArrayOfGenericType(int size) {
        //! array = new T[size]; // Illegal
        array = (T[])new Object[size]; // "unchecked" Warning
      }
      // Illegal:
      //! public <U> U[] makeArray() { return new U[10]; }
    } ///:~
    

    16.6 创建测试数据

    16.6.1 Arrays.fill()

    只能用一个值填充各个位置,而针对对象而言,就是复制同一个引用进行填充:

    import java.util.*;
    import static net.mindview.util.Print.*;
    public class FillingArrays {
      public static void main(String[] args) {
        int size = 6;
        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];
        Arrays.fill(a1, true);
        print("a1 = " + Arrays.toString(a1));
        Arrays.fill(a2, (byte)11);
        print("a2 = " + Arrays.toString(a2));
        Arrays.fill(a3, 'x');
        print("a3 = " + Arrays.toString(a3));
        Arrays.fill(a4, (short)17);
        print("a4 = " + Arrays.toString(a4));
        Arrays.fill(a5, 19);
        print("a5 = " + Arrays.toString(a5));
        Arrays.fill(a6, 23);
        print("a6 = " + Arrays.toString(a6));
        Arrays.fill(a7, 29);
        print("a7 = " + Arrays.toString(a7));
        Arrays.fill(a8, 47);
        print("a8 = " + Arrays.toString(a8));
        Arrays.fill(a9, "Hello");
        print("a9 = " + Arrays.toString(a9));
        // Manipulating ranges:
        Arrays.fill(a9, 3, 5, "World");
        print("a9 = " + Arrays.toString(a9));
      }
    } /* Output:
    a1 = [true, true, true, true, true, true]
    a2 = [11, 11, 11, 11, 11, 11]
    a3 = [x, x, x, x, x, x]
    a4 = [17, 17, 17, 17, 17, 17]
    a5 = [19, 19, 19, 19, 19, 19]
    a6 = [23, 23, 23, 23, 23, 23]
    a7 = [29.0, 29.0, 29.0, 29.0, 29.0, 29.0]
    a8 = [47.0, 47.0, 47.0, 47.0, 47.0, 47.0]
    a9 = [Hello, Hello, Hello, Hello, Hello, Hello]
    a9 = [Hello, Hello, Hello, World, World, Hello]
    *///:~
    

    使用Arrays.fill()可以填充整个数组,或者只填充某个区域。

    16.6.2 数据生成器

    package net.mindview.util;
    public class CountingGenerator {
        static char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
        public CountingGenerator() {
        }
        public static class Boolean implements Generator<java.lang.Boolean> {
            private boolean value = false;
            public Boolean() {
            }
            public java.lang.Boolean next() {
                this.value = !this.value;
                return this.value;
            }
        }
        public static class Byte implements Generator<java.lang.Byte> {
            private byte value = 0;
            public Byte() {
            }
            public java.lang.Byte next() {
                return this.value++;
            }
        }
        public static class Character implements Generator<java.lang.Character> {
            int index = -1;
            public Character() {
            }
            public java.lang.Character next() {
                this.index = (this.index + 1) % CountingGenerator.chars.length;
                return CountingGenerator.chars[this.index];
            }
        }
        public static class Double implements Generator<java.lang.Double> {
            private double value = 0.0D;
            public Double() {
            }
            public java.lang.Double next() {
                double result = (double)(this.value++);
                return result;
            }
        }
        public static class Float implements Generator<java.lang.Float> {
            private float value = 0.0F;
            public Float() {
            }
            public java.lang.Float next() {
                float result = this.value;
                this.value = (float)((double)this.value + 1.0D);
                return result;
            }
        }
        public static class Integer implements Generator<java.lang.Integer> {
            private int value = 0;
            public Integer() {
            }
            public java.lang.Integer next() {
                return this.value++;
            }
        }
        public static class Long implements Generator<java.lang.Long> {
            private long value = 0L;
    
            public Long() {
            }
            public java.lang.Long next() {
                return java.lang.Long.valueOf((long)(this.value++));
            }
        }
        public static class Short implements Generator<java.lang.Short> {
            private short value = 0;
            public Short() {
            }
            public java.lang.Short next() {
                return this.value++;
            }
        }
        public static class String implements Generator<java.lang.String> {
            private int length = 7;
            Generator<java.lang.Character> cg = new CountingGenerator.Character();
            public String() {
            }
            public String(int length) {
                this.length = length;
            }
            public java.lang.String next() {
                char[] buf = new char[this.length];
    
                for(int i = 0; i < this.length; ++i) {
                    buf[i] = ((java.lang.Character)this.cg.next()).charValue();
                }
                return new java.lang.String(buf);
            }
        }
    }
    

    通过反射使用这个工具:

    import net.mindview.util.*;
    
    public class GeneratorsTest {
      public static int size = 10;
      public static void test(Class<?> surroundingClass) {
        for(Class<?> type : surroundingClass.getClasses()) {
          System.out.print(type.getSimpleName() + ": ");
          try {
            Generator<?> g = (Generator<?>)type.newInstance();
            for(int i = 0; i < size; i++)
              System.out.printf(g.next() + " ");
            System.out.println();
          } catch(Exception e) {
            throw new RuntimeException(e);
          }
        }
      }
      public static void main(String[] args) {
        test(CountingGenerator.class);
      }
    } /* Output:
    Double: 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
    Float: 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
    Long: 0 1 2 3 4 5 6 7 8 9
    Integer: 0 1 2 3 4 5 6 7 8 9
    Short: 0 1 2 3 4 5 6 7 8 9
    String: abcdefg hijklmn opqrstu vwxyzAB CDEFGHI JKLMNOP QRSTUVW XYZabcd efghijk lmnopqr
    Character: a b c d e f g h i j
    Byte: 0 1 2 3 4 5 6 7 8 9
    Boolean: true false true false true false true false true false
    *///:~
    

    使用随机数生成器的Generator:

    package net.mindview.util;
    
    import java.util.Random;
    
    public class RandomGenerator {
        private static Random r = new Random(47L);
    
        public RandomGenerator() {
        }
    
        public static class Boolean implements Generator<java.lang.Boolean> {
            public Boolean() {
            }
    
            public java.lang.Boolean next() {
                return RandomGenerator.r.nextBoolean();
            }
        }
    
        public static class Byte implements Generator<java.lang.Byte> {
            public Byte() {
            }
    
            public java.lang.Byte next() {
                return (byte)RandomGenerator.r.nextInt();
            }
        }
    
        public static class Character implements Generator<java.lang.Character> {
            public Character() {
            }
    
            public java.lang.Character next() {
                return CountingGenerator.chars[RandomGenerator.r.nextInt(CountingGenerator.chars.length)];
            }
        }
    
        public static class Double implements Generator<java.lang.Double> {
            public Double() {
            }
    
            public java.lang.Double next() {
                long trimmed = Math.round(RandomGenerator.r.nextDouble() * 100.0D);
                return (double)trimmed / 100.0D;
            }
        }
    
        public static class Float implements Generator<java.lang.Float> {
            public Float() {
            }
    
            public java.lang.Float next() {
                int trimmed = Math.round(RandomGenerator.r.nextFloat() * 100.0F);
                return (float)trimmed / 100.0F;
            }
        }
    
        public static class Integer implements Generator<java.lang.Integer> {
            private int mod = 10000;
    
            public Integer() {
            }
    
            public Integer(int modulo) {
                this.mod = modulo;
            }
    
            public java.lang.Integer next() {
                return RandomGenerator.r.nextInt(this.mod);
            }
        }
    
        public static class Long implements Generator<java.lang.Long> {
            private int mod = 10000;
    
            public Long() {
            }
    
            public Long(int modulo) {
                this.mod = modulo;
            }
    
            public java.lang.Long next() {
                return new java.lang.Long((long)RandomGenerator.r.nextInt(this.mod));
            }
        }
    
        public static class Short implements Generator<java.lang.Short> {
            public Short() {
            }
    
            public java.lang.Short next() {
                return (short)RandomGenerator.r.nextInt();
            }
        }
    
        public static class String extends net.mindview.util.CountingGenerator.String {
            public String() {
                this.cg = new RandomGenerator.Character();
            }
    
            public String(int length) {
                super(length);
                this.cg = new RandomGenerator.Character();
            }
        }
    }
    

    16.6.3 从Generator中创建数组

    这个工具只能产生Object子类型数组,而不能产生基本类型数组:

    package net.mindview.util;
    
    import java.lang.reflect.Array;
    
    public class Generated {
        public Generated() {
        }
    
        public static <T> T[] array(T[] a, Generator<T> gen) {
            return (new CollectionData(gen, a.length)).toArray(a);
        }
    
        public static <T> T[] array(Class<T> type, Generator<T> gen, int size) {
            Object[] a = (Object[])Array.newInstance(type, size);
            return (new CollectionData(gen, size)).toArray(a);
        }
    }
    

    使用反射动态创建具有恰当类型和数量的新数组,然后使用与第一个方法相同的技术来填充该数组:

    import java.util.*;
    import net.mindview.util.*;
    
    public class TestGenerated {
      public static void main(String[] args) {
        Integer[] a = { 9, 8, 7, 6 };
        System.out.println(Arrays.toString(a));
        a = Generated.array(a,new CountingGenerator.Integer());
        System.out.println(Arrays.toString(a));
        Integer[] b = Generated.array(Integer.class,
            new CountingGenerator.Integer(), 15);
        System.out.println(Arrays.toString(b));
      }
    } /* Output:
    [9, 8, 7, 6]
    [0, 1, 2, 3]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
    *///:~
    

    泛型不能用于基本类型,可以用生成器来填充基本类型。
    创建一个转换器,它可以接受任意的包装器对象数组,并将其转化为相应的基本类型数组:

    package net.mindview.util;
    
    public class ConvertTo {
        public ConvertTo() {
        }
    
        public static boolean[] primitive(Boolean[] in) {
            boolean[] result = new boolean[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].booleanValue();
            }
    
            return result;
        }
    
        public static char[] primitive(Character[] in) {
            char[] result = new char[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].charValue();
            }
    
            return result;
        }
    
        public static byte[] primitive(Byte[] in) {
            byte[] result = new byte[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].byteValue();
            }
    
            return result;
        }
    
        public static short[] primitive(Short[] in) {
            short[] result = new short[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].shortValue();
            }
    
            return result;
        }
    
        public static int[] primitive(Integer[] in) {
            int[] result = new int[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].intValue();
            }
    
            return result;
        }
    
        public static long[] primitive(Long[] in) {
            long[] result = new long[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].longValue();
            }
    
            return result;
        }
    
        public static float[] primitive(Float[] in) {
            float[] result = new float[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].floatValue();
            }
    
            return result;
        }
    
        public static double[] primitive(Double[] in) {
            double[] result = new double[in.length];
    
            for(int i = 0; i < in.length; ++i) {
                result[i] = in[i].doubleValue();
            }
    
            return result;
        }
    }
    

    16.7 Arrays实用功能

    Arrays类有一套用于static实用方法,它有六个基本方法:equals()比较数组,deepEquals()比较多维数组;fill()填充;sort()用于对数组排序;binarySearch()用于在排序的数组中查找元素;toString()产生数组的String表示;hashCode()产生数组的散列码。

    16.7.1 复制数组

    System.arraycopy()它复制数组比for快:

    import java.util.*;
    import static net.mindview.util.Print.*;
    
    public class CopyingArrays {
      public static void main(String[] args) {
        int[] i = new int[7];
        int[] j = new int[10];
        Arrays.fill(i, 47);
        Arrays.fill(j, 99);
        print("i = " + Arrays.toString(i));
        print("j = " + Arrays.toString(j));
        System.arraycopy(i, 0, j, 0, i.length);
        print("j = " + Arrays.toString(j));
        int[] k = new int[5];
        Arrays.fill(k, 103);
        System.arraycopy(i, 0, k, 0, k.length);
        print("k = " + Arrays.toString(k));
        Arrays.fill(k, 103);
        System.arraycopy(k, 0, i, 0, k.length);
        print("i = " + Arrays.toString(i));
        // Objects:
        Integer[] u = new Integer[10];
        Integer[] v = new Integer[5];
        Arrays.fill(u, new Integer(47));
        Arrays.fill(v, new Integer(99));
        print("u = " + Arrays.toString(u));
        print("v = " + Arrays.toString(v));
        System.arraycopy(v, 0, u, u.length/2, v.length);
        print("u = " + Arrays.toString(u));
      }
    } /* Output:
    i = [47, 47, 47, 47, 47, 47, 47]
    j = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
    j = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]
    k = [47, 47, 47, 47, 47]
    i = [103, 103, 103, 103, 103, 47, 47]
    u = [47, 47, 47, 47, 47, 47, 47, 47, 47, 47]
    v = [99, 99, 99, 99, 99]
    u = [47, 47, 47, 47, 47, 99, 99, 99, 99, 99]
    *///:~
    

    System.arraycopy()不会执行自动包装,两个数组必须具有相同的确切类型。

    16.7.2 数组的比较

    import java.util.*;
    import static net.mindview.util.Print.*;
    
    public class ComparingArrays {
      public static void main(String[] args) {
        int[] a1 = new int[10];
        int[] a2 = new int[10];
        Arrays.fill(a1, 47);
        Arrays.fill(a2, 47);
        print(Arrays.equals(a1, a2));
        a2[3] = 11;
        print(Arrays.equals(a1, a2));
        String[] s1 = new String[4];
        Arrays.fill(s1, "Hi");
        String[] s2 = { new String("Hi"), new String("Hi"),
          new String("Hi"), new String("Hi") };
        print(Arrays.equals(s1, s2));
      }
    } /* Output:
    true
    false
    true
    *///:~
    

    16.7.3 数组元素的比较

    排序必须根据对象的实际类型执行比较操作。
    程序设计的基本目标是:将保存不变的事物与会发生改变的事物相分离。这里,不变的是通用的排序算法,变化的是各种对象相互比较的方式。通过使用策略设计模式,可以将会发生变化的代码封装在单独的类中(策略对象),你可以将策略对象传递给总是相同的代码。
    一种比较实现Comparable接口:

    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Print.*;
    
    public class CompType implements Comparable<CompType> {
      int i;
      int j;
      private static int count = 1;
      public CompType(int n1, int n2) {
        i = n1;
        j = n2;
      }
      public String toString() {
        String result = "[i = " + i + ", j = " + j + "]";
        if(count++ % 3 == 0)
          result += "
    ";
        return result;
      }
      public int compareTo(CompType rv) {
        return (i < rv.i ? -1 : (i == rv.i ? 0 : 1));
      }
      private static Random r = new Random(47);
      public static Generator<CompType> generator() {
        return new Generator<CompType>() {
          public CompType next() {
            return new CompType(r.nextInt(100),r.nextInt(100));
          }
        };
      }
      public static void main(String[] args) {
        CompType[] a =
          Generated.array(new CompType[12], generator());
        print("before sorting:");
        print(Arrays.toString(a));
        Arrays.sort(a);
        print("after sorting:");
        print(Arrays.toString(a));
      }
    } /* Output:
    before sorting:
    [[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
    , [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
    , [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
    , [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
    ]
    after sorting:
    [[i = 9, j = 78], [i = 11, j = 22], [i = 16, j = 40]
    , [i = 20, j = 58], [i = 22, j = 7], [i = 51, j = 89]
    , [i = 58, j = 55], [i = 61, j = 29], [i = 68, j = 0]
    , [i = 88, j = 28], [i = 93, j = 61], [i = 98, j = 61]
    ]
    *///:~
    

    另一种方法,Collection类包含一个reverseOrder()fangfa,该方法可以产生一个Comparator,它可以反转自然排序顺序:

    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Print.*;
    
    public class Reverse {
      public static void main(String[] args) {
        CompType[] a = Generated.array(
          new CompType[12], CompType.generator());
        print("before sorting:");
        print(Arrays.toString(a));
        Arrays.sort(a, Collections.reverseOrder());
        print("after sorting:");
        print(Arrays.toString(a));
      }
    } /* Output:
    before sorting:
    [[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
    , [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
    , [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
    , [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
    ]
    after sorting:
    [[i = 98, j = 61], [i = 93, j = 61], [i = 88, j = 28]
    , [i = 68, j = 0], [i = 61, j = 29], [i = 58, j = 55]
    , [i = 51, j = 89], [i = 22, j = 7], [i = 20, j = 58]
    , [i = 16, j = 40], [i = 11, j = 22], [i = 9, j = 78]
    ]
    *///:~
    

    也可以自己编写Comparator:

    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Print.*;
    
    class CompTypeComparator implements Comparator<CompType> {
      public int compare(CompType o1, CompType o2) {
        return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1));
      }
    }
    public class ComparatorTest {
      public static void main(String[] args) {
        CompType[] a = Generated.array(
          new CompType[12], CompType.generator());
        print("before sorting:");
        print(Arrays.toString(a));
        Arrays.sort(a, new CompTypeComparator());
        print("after sorting:");
        print(Arrays.toString(a));
      }
    } /* Output:
    before sorting:
    [[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
    , [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
    , [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
    , [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
    ]
    after sorting:
    [[i = 68, j = 0], [i = 22, j = 7], [i = 11, j = 22]
    , [i = 88, j = 28], [i = 61, j = 29], [i = 16, j = 40]
    , [i = 58, j = 55], [i = 20, j = 58], [i = 93, j = 61]
    , [i = 98, j = 61], [i = 9, j = 78], [i = 51, j = 89]
    ]
    *///:~
    

    16.7.4 数组排序

    使用内置的排序方法,就可以对任意的基本类型数组排序,也可以对任意的对象数组进行排序,只要该对象实现了Comparable接口或具有关联的Comparator。
    随机生成String对象,并排序:

    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Print.*;
    
    public class StringSorting {
      public static void main(String[] args) {
        String[] sa = Generated.array(new String[20],
          new RandomGenerator.String(5));
        print("Before sort: " + Arrays.toString(sa));
        Arrays.sort(sa);
        print("After sort: " + Arrays.toString(sa));
        Arrays.sort(sa, Collections.reverseOrder());
        print("Reverse sort: " + Arrays.toString(sa));
        Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);
        print("Case-insensitive sort: " + Arrays.toString(sa));
      }
    }
    

    排序算法针对正排序的特殊类型进行了优化——针对基本类型设计的"快速排序",以及针对对象设计的"稳定归并排序"。

    16.7.5 在已排序的数组中查找

    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Print.*;
    public class ArraySearching {
      public static void main(String[] args) {
        Generator<Integer> gen =
          new RandomGenerator.Integer(1000);
        int[] a = ConvertTo.primitive(
          Generated.array(new Integer[25], gen));
        Arrays.sort(a);
        print("Sorted array: " + Arrays.toString(a));
        while(true) {
          int r = gen.next();
          int location = Arrays.binarySearch(a, r);
          if(location >= 0) {
            print("Location of " + r + " is " + location +
              ", a[" + location + "] = " + a[location]);
            break; // Out of while loop
          }
        }
      }
    } 
    

    如果使用Comparator排序某个对象数组,在使用binarySearch()时必须提供同样的Comparator。

    import java.util.*;
    import net.mindview.util.*;
    public class AlphabeticSearch {
      public static void main(String[] args) {
        String[] sa = Generated.array(new String[30],
          new RandomGenerator.String(5));
        Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);
        System.out.println(Arrays.toString(sa));
        int index = Arrays.binarySearch(sa, sa[10],
          String.CASE_INSENSITIVE_ORDER);
        System.out.println("Index: "+ index + "
    "+ sa[index]);
      }
    } /* Output:
    [bkIna, cQrGs, cXZJo, dLsmw, eGZMm, EqUCB, gwsqP, hKcxr, HLGEa, HqXum, HxxHv, JMRoE, JmzMs, Mesbt, MNvqe, nyGcF, ogoYW, OneOE, OWZnT, RFJQA, rUkZP, sgqia, slJrL, suEcU, uTpnX, vpfFv, WHkjU, xxEAJ, YNzbr, zDyCy]
    Index: 10
    HxxHv
    *///:~
    
  • 相关阅读:
    敏捷开发中的sprint是什么意思_百度知道
    桐君堂_百度百科
    HSTS Preloading
    做CloudXNS产品运营的这半年 – CHINA Testers
    java~spring-ioc的使用
    java~api返回值的标准化
    java8的函数式接口
    redis使用场景和java测试案例
    springboot~注册bean的方法
    学生信息管理系统问题集锦
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/11288408.html
Copyright © 2011-2022 走看看