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
    *///:~
    
  • 相关阅读:
    Spring spEL
    Spring 使用外部部署文件
    Spring 自动装配
    spring 属性配置细节
    hdu 1054 Strategic Game
    fzu 2037 Maximum Value Problem
    将博客搬至CSDN
    HDU 4714 Tree2Cycle
    HDU 1009 The Shortest Path in Nya Graph
    POJ 1942 Paths on a Grid 组合数的优化
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/11288408.html
Copyright © 2011-2022 走看看