第十四章、数组

数组是指一组数据的集合,数组中的每个数据称为元素。在 Java 中,数组也是 Java 对象。数组中的元素可以是任意类型(包括基本类型和引用类型),但同一个数组里只能存放类型相同的元素。

14.1 数组变量的声明与创建

声明

int[] scores;               //int scores[];
String[] names;             //String names[];   同样合法
int[][] matrix;             //int x[][]; int[]x[];

创建

int[] scores = new int[100];

数组对象和其他 Java 对象一样,也用 new 语句创建。new 语句执行以下步骤:

  1. 堆区中为数组分配内存空间。
  2. 为数组中的每个元素赋予其数据类型的默认值。
  3. 返回数组对象的引用。

对于Java 类的程序入口方法 main(String[] args),如果运行这个类时没有输入参数,那么 main() 方法的参数 args 并不是 null, 而是一个长度为 0 的数组。

数组对象创建后,它的长度是固定的。数组对象的长度是无法改变的,但是数组变量可以改变所引用的数组对象。

int[] x = new int[1];
int[] y = x;
x = new int[4];

数组被创建后,每个元素被自动赋予其数据类型的默认值,还可以在程序中将数组元素显式地初始化。

int[] a = {4, 5, 6};
int[] b = new int[] {4, 5, 6};

int[] x= new int[5] {5, 4, 3, 2, 1};//编译出错,不能在[]中指定数组的长度
int[]x; x = {5, 4, 3, 2, 1};        //编译出错,{5,4,3..}必须在声明数组变量语句中使用,不能单独使用

14.2 访问数组的元素和长度

数组中的每个元素都有一个索引,或者称为下标。数组中的第一个元素的索引为0。

所有 Java 数组都有一个长度属性,它的声明形式为:

public final length;

当数组的元素为引用类型,数组中存放的是对象的引用,而不是对象本身。

StringBuffer sb = new StringBuffer("a");                //创建一个StringBuffer对象
StringBuffer[] sbs = new StringBuffer[]{sb, null};      //把他的引用加入到一个StringBuffer数组中
//此时 StringBuffer 对象 被变量sb引用,且也被 StringBuffer 数组中的第一个元素引用

sb.append("b"); 
sb = null;
System.out.println(sb);                                 //打印null  
sbs[0].append("c");
System.out.println(sbs[0]);                             //打印abc
sbs[0] = null;                                          //StringBuffer对象结束生命周期
sbs = null;                                             //StringBuffer数组对象结束生命周期

//第三行和第六行都向同一个StringBuffer对象添加字符
//第八行执行完,StringBuffer对象不被任何引用变量引用

14.3 多维数组以及不规则数组

Java 支持多维数组,并且支持不规则数组,即多维数组中两维以上的子数组的长度不一样。

int[][] matrix = {
    {1},
    {1, 2, 3},
    {5, 6, 7, 8}
}

创建多维数组时,必须按照从低纬度到高纬度的顺序创建每一维数组。

int[][][] a = new int[2][][3];              //编译出错,必须先创建第二维数组再创建第三维数组

14.4 调用数组对象的方法

Java 数组继承了 Object 类,因此继承了Object类的所有方法。比如 equals(),还可以用 instanceof 操作符。

int[] a = new int[4];
int[] b = new int[4];
boolean b1 = a instanceof Object;
boolean b2 = a instanceof int[];
boolean b3 = a.equals(b);           //false

14.10 哈希表

在一般的数组中,元素的取值和元素的位置之间不存在确定的关系,因此,在数组中查找特定值时,需要把查找值和 一系列的元素进行比较。如果元素的值 value 和它在数组中的索引位置 index 有一个确定的对应关系 hash(),那么对于给定的值,只要调用哈希方法,就能找到数组中取值为 value 的元素的位置。如果数组中元素的值和位置存在确定的对应关系,这样的数组称为 哈希表,这种数组的优点是能够提高查找数据的效率。

hash() 方法的返回值也称为元素的哈希码,但在哈希码很大或存在哈希冲突情况下,不能把哈希码直接作为元素的位置。

//MyHashSet.java

class Node {
    private Object value;
    private Node next;

    public Node(Object vlaue) { this.value = value; }
    public Object getValue() { return value; }
    public Node getNext() { return next; }
    public void setNext(Node next) { this.next = next; }
}

public classMyHashSet {
    private Node[] array;
    private int size = 0;               
    public MyHashSet(int length) { array = new Node[length]; }
    public int size() {return size;}

    private static int hash(Object o) {             //获得对象的改善的哈希码
        int h = o.hashCode();
        h += ~ (h << 9);
        h ^= (h >>> 14);
        h += (h << 4);
        h ^= (h >>> 10);
        return h;
    }

    private int indexFor(int hashCode) {            //通过对象哈希码获得其索引位置
        return hashCode & (array.length - 1);
    }

    public void add(Object value) {
        int index = indexFor(hash(value));
        System.out.println("index: " + index + "value: " + value);
        Node newNode = new Node(value);
        Node node = array[index];
        if (node == null) {
            array[index] = new Node;
            size++;
        } else {                                    //哈希冲突
            Node nextNode;
            while (!node.getValue().equals(value)  
                    && (nextNode = node.getNext())!= null) {
                node = nextNode;
            }
            if (!node.getValue().equals(value)) {
                node.setNext(newNode);
                size++;
            }
        }   
    }

    public boolean contains(Object value) {         //测试集合中是否存在指定对象
        int index = indexFor(hash(value));
        Node node = array[index];
        while (node != null && !node.getValue().equals(value)) {
            node = node.getNext();
        }
        if (node != null && node.getValue().equals(value))
            return true;
        else 
            return false;
    }

    public boolean remove(Object value) {            //删除集合中的一个对象
        int index = indexFor(hash(value));
        Node node = array[index];
        if (node != null && node.getValue().equals(value)) {
            array[index] = node.getNext();
            size--;
            return true;
        }
        Node lastNode = null;
        while (node != null && !node.getValue().equals(value)) {
            lastNode = node;
            node = node.getNext();
        }
        if (node != null && node.getValue().equals(value)) {
            lastNode.setNext(node.getNext());
            size--return true;
        } else {
            reutrn false;
        }
    }
    
    public Object[] getAll() {
        Object[] values = new Object[size];
        int index = 0;
        for (Node node : array) {
            while (node != null) {
                values[index++] = node.getValue();
                node = node.getNext();
            }
        }
        return values;
    }
    public static void main(String[] args) {
        MyHashSet set = new MyHashSet(6);
        Object[] values = {"Tom", "Mike","Mike","Jack", "Mary", "Linda","Rose","Jone"};
        for (Object value : values) set.add(value);
        set.remove("Mary");
        values = set.getAll();
        ...
    }
}
//array[0] -> Node(Linda) -> Node(Rose) -> Node(Jone)
//array[1] -> Node(Mike)
//array[2] null
//array[3] null
//array[4] -> Node(Tom)
//array[5] -> Node(Jack) -> Node(Mary)

14.11 数组实用类:Array

  • equals():比较两个数组是否相同。只有当两个数组中的元素数目相同,并且对应位置的元素都相同时,才表明数组相同。
  • fill():向数组中填充数据
  • sort():把数组中的元素按升序排列。如果数组中的元素为引用类型,会采用自然排序方式。
  • parallelSort():开启多个线程,以并发的方式对数组中的元素进行排序,提高排序的效率。
  • binarySearch():按照二分查找算法,查找数组中值与给定数据相同的元素。在调用该方法时,必须保证数组中的元素已经按照升序排列,这样才能得到正确的结果。
  • asList():把数组转换成一 个 List 对象,将其返回。
  • toString():返回包含数组中所有元素信息的字符串。

以上每个方法都有多种重载形式

14.12 声明数目可变参数

为了进一步简化编程,JDK5增加了一个新特性:用符号... 来声明数目可变参数(简称为可变参数)。可变参数适用于参数的数目不确定,而类型确定的情况。

void method(int a, float b, String... c)

可变参数具有以下特点:

  • 只能出现在参数列表的最后,作为最后一个参数。
  • 符号...位于参数类型和参数名之间,前后有无空格都可以。
  • Java 虚拟机在运行时为可变参数隐含创建一个数组,因此在方法体内允许以数组的形式访问可变参数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值