第16章 数组

1、对数组的基本看法:可以创建并组装它们,通过使用整型索引值访问它们的元素,并且它们的尺寸不能改变。
16.1数组为什么特殊?
1、数组与其他种类的容器之间的区别有三个方面:效率、类型和保存基本类型的能力。
2、数组是一种效率最高的存储和随机访问对象引用序列的方式。
3、数组就是一个简单的线性序列,这使得元素访问非常快速。但是这种速度所付出的代价是数组对象的大小被固定,并且在其 生命周期中不可改变。
4、ArrayList通过创建一个新的实例,然后把旧实例中所有的引用迁移到新实例中,从而实现更多空间的自动分配,尽管通常应该首选ArrayList而不是数组,但是这种弹性需要开销。因此,ArrayList的效率比数组低很多。
5、在泛型之前,其他的容器类在处理对象时,都将它们视作没有任何具体类型。也就是说,它们将这些对象都当作Java中所有类的根类Object处理。数组之所以优于泛型之前的容器,就是因为可以创建一个数组去持有某种具体类型。这意味着可以通过编译器检查,来防止插入错误类型和抽取不当类型,当然,无论在编译时还是运行时,Java都会阻止你向对象发送不恰当的消息。所以,并不是说哪种方法更不安全,只是如果编译时就能够之处错误,会显得更加优雅,也减少了程序的使用者被异常吓着的可能性。
6、数组可以持有基本类型,而泛型之前的容器则不能。但是有了泛型,容器就可以指定并检查它们所持有对象的类型,并且有了自动包装机制,容器看起来还能够持有基本类型。
16.2 数组是第一级对象
1、无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建了一个真实对象,这个(数组)对象用难以保存指向其他对象的引用,可以作为数组初始化语法的一部分隐士地创建此对象,或者用new表达式显示地创建。只读成员length是数组对象的一部分(事实上,这是唯一一个可以访问的字段或方法),表示此数组对象可以存储多少元素。
2、基本类型数组的工作方式与对象数组一样,不过基本类型的数组直接存储基本类型数据的值。
16.3返回一个数组
1、

package com16;

import java.util.Arrays;
import java.util.Random;

/**
 * Created by Panda on 2018/5/16.
 */
public class Test1 {
    private static Random random =new Random(47);
    static final String[] FL={"1","2","3","4","5","6","7","8"};
    public static String[] falvorSet(int n){
        if(n>FL.length){
            System.out.println("error");
        }
        String[] result=new String[n];
        boolean[] picked=new boolean[FL.length];
        for (int i = 0; i <n ; i++) {
            int t;
            do t=random.nextInt(FL.length);
            while (picked[t]);
            result[i]=FL[t];
            picked[t]=true;
        }
        return result;
    }
    public static void main(String[] args) {
        for (int i = 0; i <7 ; i++) {
            System.out.println(Arrays.toString(falvorSet(3)));
        }
    }
    /**
     *
      [6, 4, 5]
     [1, 2, 5]
     [2, 4, 5]
     [6, 3, 8]
     [3, 1, 5]
     [7, 2, 5]
     [5, 2, 4]
     */
}
public class Test2 {
    public static void main(String[] args) {
        int[][][] a=new int[2][3][4];
        System.out.println(a.length);  //2
    }
}

16.4 多维数组
16.5数组与泛型
1、通常,数组与泛型不能很好地结合。不能实例化具有参数化类型的数:
Peel[Banana][] peels =new Peel[10];
擦除会移除参数类型信息,而数组必须知道它们所持有的确切类型,以强制保证类型安全。
2、可以参数化数组本身的类型。

package com16;

/**
 * Created by Panda on 2018/5/16.
 */
class ClassParameter<T>{
    public T[] f(T[] arg){return arg;};
}
class MethodParameter{
    public static <T> T[] f(T[] arg){return arg;}
}
public class Test3 {
    public static void main(String[] args) {
        Integer[] ints={1,2,3,4,5};
        Double[] doubles ={1.1,1.2,1.3,1.4,1.5};
        Integer[] integers=new ClassParameter<Integer>().f(ints);
        Double[] doubles1=new ClassParameter<Double>().f(doubles);
        integers=MethodParameter.f(integers);
        doubles1=MethodParameter.f(doubles1);
    }
}

3、不能创建实际的持有泛型的数组对象,但是可以创建非泛型的数组,然后将其转型。
16.6创建测试数据
16.6.1
1、Arrays.fill():只能用同一个值填充各个位置,而针对对象而言,就是复制同一个引用进行填充。填充部分,填充整体。
16.6.2数据生成器
16.6.3从Generator中创建数组
1、为了接收Genenrator并产生数组,需要两个转换工具。第一个工具使用任意的Generator来产生Object子类型的数组。为了处理基本类型,第二个工具接收任意基本类型的包装类型数组,并产生相应的基本类型数组。
16.7 Arrays实用功能
1、Arrays.asList()接受任意的序列或数组作为参数,并将其转变为List容器。
16.7.1 复制数组

package com16;

import java.util.Arrays;

/**
 * Created by Panda on 2018/5/17.
 */
//System.arraycopy() 不会允许自动包装和自动拆包,两个数组必须具有相同的确切类型。
    //基本类型数组与对象数组都可以复制
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);
        System.out.println("i= "+Arrays.toString(i));
        System.out.println("j= "+Arrays.toString(j));
        System.arraycopy(i,0,j,0,i.length);
        System.out.println("j= "+Arrays.toString(j));
        int[] k= new int[5];
        Arrays.fill(k,103);
        System.out.println("k= "+Arrays.toString(k));
        System.arraycopy(i,0,k,0,k.length);
        System.out.println("k= "+Arrays.toString(k));
        Arrays.fill(k,103);
        System.arraycopy(k,0,i,0,k.length);
        System.out.println("i= "+Arrays.toString(k));

        Integer[] u=new Integer[10];
        Integer[] v=new Integer[5];
        Arrays.fill(u,new Integer(47));
        Arrays.fill(v,new Integer(99));
        System.out.println("u= "+Arrays.toString(u));
        System.out.println("v= "+Arrays.toString(v));
        System.arraycopy(v,0,u,u.length/2,v.length);
        System.out.println("u= "+Arrays.toString(u));
    }
    /**
     * 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= [103, 103, 103, 103, 103]
     k= [47, 47, 47, 47, 47]
     i= [103, 103, 103, 103, 103]
     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]
     */
}

16.7.2 数组的比较
1、Arrays类提供了重载后的equals()方法,用来比较整个数组。同样,此方法针对所有基本类型与Object都做了重载。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等,可以通过对每一个元素使用equals()做比较判断。(对于基本类型,需要使用基本类型的包装器类equals()方法,对于int类型使用Integer.equals()作比较)

package com16;

import com.sun.javafx.collections.FloatArraySyncer;

import java.util.Arrays;

/**
 * Created by Panda on 2018/5/17.
 */
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);
        System.out.println(Arrays.equals(a1,a2));   //true
        a2[3]=11;
        System.out.println(Arrays.equals(a1,a2));     //false
        String[] s1=new String[4];
        Arrays.fill(s1,"hi");
        String[] s2={new String("hi"),new String("hi"),new String("hi"),new String("hi")};
        System.out.println(Arrays.equals(s1,s2));    //true   数组相等是基于内容的
    }
}

16.7.3 数组元素的比较
1、Java有两种方式来提供比较功能。第一种是实现java.lang.Comparable接口,使类具有“天生”的比较能力。此接口很简单,只有compareTo()一个方法。此方法接收另一个Object为参数,如果当前对象小于参数则返回负值,如果相等则返回零,如果当前对象大于参数则返回正值。
2、Collections类包含一个reverseOrder()方法,该方法可以产生一个Comparator,可以反转自然的排序顺序。
16.7.4数组排序
1、使用内置的排序方法,就可以对任意的基本类型数组排序;也可以对任意的对象数组进行排序,只要该对象实现了Comparable接口或具有相关联的Comparator。
16.7.5在已排序的数组中查找
1、可以使用Arrays.binarySearch()执行快速查找。如果要对未排序的数组使用binarySearch(),那么将产生不可预料的结果。
2、如果找到了目标,Arrays.binarySearch()产生的返回值等于或大于0,具体位置。否则,它产生负返回值,表示若要保持数组的排序状态此目标元素所应该插入的位置。这个负值的计算方式是:-(插入点)-1。“插入点”是指,第一个大于查找对象的元素在数组中的位置,如果数组中所有的元素都小于要查找的对象,“插入点”就等于a.size()
3、如果数组包含重复的元素,则无法保证找到的是这些副本中的哪一个。搜索算法确实不是专为包含重复元素的数组而设计的,不过仍然可用。如果需要对没有重复的数组排序,可以使用TreeSet(保持排序顺序),或者LinkedHashSet(保持插入顺序)。
4、如果使用 Comparator排序了某个对象数组(基本类型数组无法使用Comparator进行排序),在使用binarySearch()时必须提供同样的Comparator。
16.8总结

猜你喜欢

转载自blog.csdn.net/Panda_____/article/details/80343550