zoukankan      html  css  js  c++  java
  • 数组

    在现在的stream和collections下,数组似乎没有什么优势了,但是不可否认它存在的必要。

    数组的几种创建方式

    // arrays/ArrayOptions.java
    // Initialization & re-assignment of arrays
    import java.util.*;
    import static onjava.ArrayShow.*;
    
    public class ArrayOptions {
      public static void main(String[] args) {
        // Arrays of objects:
        BerylliumSphere[] a; // Uninitialized local
        BerylliumSphere[] b = new BerylliumSphere[5];
    
        // The references inside the array are
        // automatically initialized to null:
        show("b", 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()
        };
    
        // Dynamic aggregate initialization:
        a = new BerylliumSphere[]{
          new BerylliumSphere(), new BerylliumSphere(),
        };
        // (Trailing comma is optional)
    
        System.out.println("a.length = " + a.length);
        System.out.println("b.length = " + b.length);
        System.out.println("c.length = " + c.length);
        System.out.println("d.length = " + d.length);
        a = d;
        System.out.println("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:
        show("f", 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:
        //- System.out.println("e.length = " + e.length);
        System.out.println("f.length = " + f.length);
        System.out.println("g.length = " + g.length);
        System.out.println("h.length = " + h.length);
        e = h;
        System.out.println("e.length = " + e.length);
        e = new int[]{ 1, 2 };
        System.out.println("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
    */

    唯一的不同之处就是对象数组存储的是对象的引用,而基元数组则直接存储基本数据类型的值。

    // arrays/RaggedArray.java
    import java.util.*;
    
    public class RaggedArray {
      static int val = 1;
      public static void main(String[] args) {
        SplittableRandom rand = new SplittableRandom(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)];
            Arrays.setAll(a[i][j], n -> val++); // [1]
          }
        }
        System.out.println(Arrays.deepToString(a));
      }
    }
    /* Output:
    [[[1], []], [[2, 3, 4, 5], [6]], [[7, 8, 9], [10, 11,
    12], []]]
    */

    倘若你不对基元数组进行显式的初始化,它的值会自动初始化。而对象数组将被初始化为 null 。

    泛型数组

    一般来说,数组和泛型并不能很好的结合。你不能实例化参数化类型的数组:

    Peel<Banana>[] peels = new Peel<Banana>[10]; // Illegal

    泛型有类型擦除,而数组必须强制的知道保存的类型,所以不能初始化。但是可以泛型化数组本身。

    // arrays/ParameterizedArrayType.java
    
    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);
      }
    }

    Arrays.fill()

    // arrays/FillingArrays.java
    // Using Arrays.fill()
    import java.util.*;
    import static onjava.ArrayShow.*;
    
    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);
        show("a1", a1);
        Arrays.fill(a2, (byte)11);
        show("a2", a2);
        Arrays.fill(a3, 'x');
        show("a3", a3);
        Arrays.fill(a4, (short)17);
        show("a4", a4);
        Arrays.fill(a5, 19);
        show("a5", a5);
        Arrays.fill(a6, 23);
        show("a6", a6);
        Arrays.fill(a7, 29);
        show("a7", a7);
        Arrays.fill(a8, 47);
        show("a8", a8);
        Arrays.fill(a9, "Hello");
        show("a9", a9);
        // Manipulating ranges:
        Arrays.fill(a9, 3, 5, "World");
        show("a9", a9);
      }
    }gedan
    /* 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]
    */

    我们要杜绝用遍历来对数组对象添加同一个值,fill方法会在底层走指令级操作。

    Arrays.setAll()

    // arrays/SimpleSetAll.java
    
    import java.util.*;
    import static onjava.ArrayShow.*;
    
    class Bob {
      final int id;
      Bob(int n) { id = n; }
      @Override
      public String toString() { return "Bob" + id; }
    }
    
    public class SimpleSetAll {
      public static final int SZ = 8;
      static int val = 1;
      static char[] chars = "abcdefghijklmnopqrstuvwxyz"
        .toCharArray();
      static char getChar(int n) { return chars[n]; }
      public static void main(String[] args) {
        int[] ia = new int[SZ];
        long[] la = new long[SZ];
        double[] da = new double[SZ];
        Arrays.setAll(ia, n -> n); // [1]
        Arrays.setAll(la, n -> n);
        Arrays.setAll(da, n -> n);
        show(ia);
        show(la);
        show(da);
        Arrays.setAll(ia, n -> val++); // [2]
        Arrays.setAll(la, n -> val++);
        Arrays.setAll(da, n -> val++);
        show(ia);
        show(la);
        show(da);
    
        Bob[] ba = new Bob[SZ];
        Arrays.setAll(ba, Bob::new); // [3]
        show(ba);
    
        Character[] ca = new Character[SZ];
        Arrays.setAll(ca, SimpleSetAll::getChar); // [4]
        show(ca);
      }
    }
    /* Output:
    [0, 1, 2, 3, 4, 5, 6, 7]
    [0, 1, 2, 3, 4, 5, 6, 7]
    [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
    [1, 2, 3, 4, 5, 6, 7, 8]
    [9, 10, 11, 12, 13, 14, 15, 16]
    [17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0]
    [Bob0, Bob1, Bob2, Bob3, Bob4, Bob5, Bob6, Bob7]
    [a, b, c, d, e, f, g, h]
    */

    并行化

    流 实际上可以存储到将近1000万,但是之后就会耗尽堆空间。常规的 setAll() 是有效的,但是如果我们能更快地处理如此大量的数字,那就更好了。 我们可以使用 setAll() 初始化更大的数组。如果速度成为一个问题,Arrays.parallelSetAll() 将(可能)更快地执行初始化(请记住并行性中描述的问题)。

    // arrays/ParallelSetAll.java
    
    import onjava.*;
    import java.util.Arrays;
    
    public class ParallelSetAll {
        static final int SIZE = 10_000_000;
    
        static void intArray() {
            int[] ia = new int[SIZE];
            Arrays.setAll(ia, new Rand.Pint()::get);
            Arrays.parallelSetAll(ia, new Rand.Pint()::get);
        }
    
        static void longArray() {
            long[] la = new long[SIZE];
            Arrays.setAll(la, new Rand.Plong()::get);
            Arrays.parallelSetAll(la, new Rand.Plong()::get);
        }
    
        public static void main(String[] args) {
            intArray();
            longArray();
        }
    }

    Arrays工具类

    • asList(): 获取任何序列或数组,并将其转换为一个 列表集合 (集合章节介绍了此方法)。

    • copyOf():以新的长度创建现有数组的新副本。

    • copyOfRange():创建现有数组的一部分的新副本。

    • equals():比较两个数组是否相等。

    • deepEquals():多维数组的相等性比较。

    • stream():生成数组元素的流。

    • hashCode():生成数组的哈希值(您将在附录中了解这意味着什么:理解equals()和hashCode())。

    • deepHashCode(): 多维数组的哈希值。

    • sort():排序数组

    • parallelSort():对数组进行并行排序,以提高速度。

    • binarySearch():在已排序的数组中查找元素。

    • parallelPrefix():使用提供的函数并行累积(以获得速度)。基本上,就是数组的reduce()。

    • spliterator():从数组中产生一个Spliterator;这是本书没有涉及到的流的高级部分。

    • toString():为数组生成一个字符串表示。你在整个章节中经常看到这种用法。

    • deepToString():为多维数组生成一个字符串。你在整个章节中经常看到这种用法。对于所有基本类型和对象,所有这些方法都是重载的。

    流和数组

    // arrays/StreamFromArray.java
    
    import java.util.*;
    import onjava.*;
    
    public class StreamFromArray {
        public static void main(String[] args) {
            String[] s = new Rand.String().array(10);
            Arrays.stream(s).skip(3).limit(5).map(ss -> ss + "!").forEach(System.out::println);
            int[] ia = new Rand.Pint().array(10);
            Arrays.stream(ia).skip(3).limit(5)
                    .map(i -> i * 10).forEach(System.out::println);
            Arrays.stream(new long[10]);
            Arrays.stream(new double[10]);
            // Only int, long and double work:
            // - Arrays.stream(new boolean[10]);
            // - Arrays.stream(new byte[10]);
            // - Arrays.stream(new char[10]);
            // - Arrays.stream(new short[10]);
            // - Arrays.stream(new float[10]);
            // For the other types you must use wrapped arrays:
            float[] fa = new Rand.Pfloat().array(10);
            Arrays.stream(ConvertTo.boxed(fa));
            Arrays.stream(new Rand.Float().array(10));
        }
    }
    /* Output:
        eloztdv!
        ewcippc!
        ygpoalk!
        ljlbynx!
        taprwxz!
        47200
        61770
        84790
        66560
        37680
    */

    数组排序

    // arrays/Reverse.java
    // The Collections.reverseOrder() Comparator
    
    import onjava.*;
    
    import java.util.Arrays;
    import java.util.Collections;
    
    import static onjava.ArrayShow.*;
    
    public class Reverse {
        public static void main(String[] args) {
            CompType[] a = new CompType[12];
            Arrays.setAll(a, n -> CompType.get());
            show("Before sorting", a);
            Arrays.sort(a, Collections.reverseOrder());
            show("After sorting", a);
        }
    }
    /* Output:
    Before sorting: [[i = 35, j = 37], [i = 41, j = 20],
                    [i = 77, j = 79] , [i = 56, j = 68],
                    [i = 48, j = 93], [i = 70, j = 7],
                    [i = 0, j = 25], [i = 62, j = 34],
                    [i = 50, j = 82] , [i = 31, j = 67],
                    [i = 66, j = 54], [i = 21, j = 6] ]
    After sorting: [[i = 77, j = 79], [i = 70, j = 7],
                    [i = 66, j = 54] , [i = 62, j = 34],
                    [i = 56, j = 68], [i = 50, j = 82] ,
                    [i = 48, j = 93], [i = 41, j = 20],
                    [i = 35, j = 37] , [i = 31, j = 67],
                    [i = 21, j = 6], [i = 0, j = 25] ]
    */

    自定义比较器

    // arrays/ComparatorTest.java
    // Implementing a Comparator for a class
    
    import onjava.*;
    
    import java.util.Arrays;
    import java.util.Comparator;
    
    import static onjava.ArrayShow.*;
    
    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 = new CompType[12];
            Arrays.setAll(a, n -> CompType.get());
            show("Before sorting", a);
            Arrays.sort(a, new CompTypeComparator());
            show("After sorting", a);
        }
    }
    /* Output:
    Before sorting:[[i = 35, j = 37], [i = 41, j = 20], [i = 77, j = 79] ,
                    [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] ,
                    [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82],
                    [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] ]
    After sorting: [[i = 21, j = 6], [i = 70, j = 7], [i = 41, j = 20] ,
                    [i = 0, j = 25], [i = 62, j = 34], [i = 35, j = 37] ,
                    [i = 66, j = 54], [i = 31, j = 67], [i = 56, j = 68] ,
                    [i = 77, j = 79], [i = 50, j = 82], [i = 48, j = 93] ]
    */

    并行排序

    // arrays/jmh/ParallelSort.java
    package arrays.jmh;
    
    import onjava.*;
    import org.openjdk.jmh.annotations.*;
    
    import java.util.Arrays;
    
    @State(Scope.Thread)
    public class ParallelSort {
        private long[] la;
    
        @Setup
        public void setup() {
            la = new Rand.Plong().array(100_000);
        }
    
        @Benchmark
        public void sort() {
            Arrays.sort(la);
        }
    
        @Benchmark
        public void parallelSort() {
            Arrays.parallelSort(la);
        }
    }

    parallelSort() 算法将大数组拆分成更小的数组,直到数组大小达到极限,然后使用普通的 Arrays .sort() 方法。然后合并结果。该算法需要不大于原始数组的额外工作空间。

    parallelPrefix()并行前缀

    // arrays/ParallelPrefix2.java
    
    import onjava.*;
    
    import java.util.Arrays;
    
    import static onjava.ArrayShow.*;
    
    public class ParallelPrefix2 {
        public static void main(String[] args) {
            String[] strings = new Rand.String(1).array(8);
            show(strings);
            Arrays.parallelPrefix(strings, (a, b) -> a + b);
            show(strings);
        }
    }
    /* Output:
    [b, t, p, e, n, p, c, c]
    [b, bt, btp, btpe, btpen, btpenp, btpenpc, btpenpcc]
    */

    还是鼓励使用集合,因为低级数组实际上不太符合面向对象的思想。

    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    poj3107 Godfather
    poj1655 Balancing Act
    bzoj2073 PRZ
    bzoj1688 疾病管理
    BZOJ——1607: [Usaco2008 Dec]Patting Heads 轻拍牛头
    BZOJ——1606: [Usaco2008 Dec]Hay For Sale 购买干草
    BZOJ——1649: [Usaco2006 Dec]Cow Roller Coaster
    BZOJ——2096: [Poi2010]Pilots
    洛谷—— P1785 漂亮的绝杀
    NOIP 2012 提高组 DAY1 T2 国王游戏
  • 原文地址:https://www.cnblogs.com/CherryTab/p/12006913.html
Copyright © 2011-2022 走看看