Java 数组初始化及常用操作

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

基础知识

很多道理往往可以用简单的话说明白。 关于 Java 数组,你只需要记住两句话:

1. 数组是相同类型数据的有序集合;

2. 数组也是对象。

展开的版本:

  1. 长度确定且不可改;
  2. 类型不可改;
  3. 类型可基本可引用;
  4. 数据的变量属于引用类型,数组也是对象,数据的元素相当于对象的属性。

Java 数组初始化的三种方式:

  1. 静态初始化:一开始就把值给好了;
  2. 动态初始化:一开始给个长度,然后再逐个赋值;
  3. 默认初始化:动态初始化前一步,然后就用这个系统默认给的值:0、0.0、false、null。

练习点:

  1. Array.toString([]);
  2. System.arraycopy(原数组, 原数组开始的索引, 要拷贝到的数组, 目标数组开始拷贝的索引, 从原数组拷贝的长度);
  3. for(type i: array) 来逐个遍历;
  4. 初始化方法;

练习代码如下:

public class CopyArray {
    public static void main(String[] args) {
        String[] companies = new String[]{"alibaba", "bytedance",
                "pinduoduo", "dingdong", "souhu"};
        String[] copy2 = new String[3];
        System.arraycopy(companies, 0, copy2, 0, 3);

        for (String s: copy2) {
            System.out.println(s);
        }
    }

}
/** 结果:
* alibaba
* bytedance
* pinduoduo
*/
复制代码
public class Test02 {

    public static void main(String[] args) {
        // 静态初始化要在声明后直接初始化。
        Man m = new Man(20,"SuperKris");
        // Man[] mans = new Man[6]; 这一行相当于没有用了
        Man[] mans = new Man[]{
                new Man(10, "Kris0"),
                new Man(11, "Kris1"),
                new Man(13, "Kris3"),
                new Man(12, "Kris2"),
                new Man(15, "Kris5"),
        };

        mans[4] = m;

        for (int i=0; i<mans.length; i++) {
            System.out.println(mans[i].getName());
        }
        // 增强 for 循环,把每一个元素取出来,放给这个变量。
        for (Man man: mans) {
            System.out.println(man);
        }
    }

}

class Man {
    private int id;
    private String name;
    
    public Man() {
    }
    public Man(int id, String name) {
        this.id = id;
        this.name = name;
    }
  
    @Override
    public String toString() {
        return "id = " + id + ", name = " + name;
    }
    //省略了 JavaBean()
   
}
复制代码
public class Test03 {
    public static void main(String[] args) {
        int[] a = {100, 200, 300};
        int[] b = {1,2,3,4234,22,45,765};

        System.out.println(Arrays.toString(a));

        Arrays.sort(b);
        System.out.println(b.toString());
        // 二分查找
        System.out.println("b: " + Arrays.toString(b));
        // 存在的话,就返回索引
        System.out.println("该元素的索引是: " + Arrays.binarySearch(b, 22));
        // 这个数不存在的话,返回负数
        System.out.println("该元素的索引是: " + Arrays.binarySearch(b, 555));

        // 把 b 从 fromIndex,到 toIndex-1 对应的位置,复制为最后一个参数  [) 区间一般都是左开右闭
        Arrays.fill(b, 0,3,500);
        System.out.println(Arrays.toString(b));

    }
}
复制代码

运行结果如下图:

image.png

小技巧

源码(在 IDEA 里按住 Alt/command 键,然后鼠标悬在想看的地方就可以访问到)

有两个要注意的地方:

1. Array.toString() 和之前 String里,Object里的 toString 不一样。

这个是普通的 toString 方法:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
复制代码

这个是 Array.toString()的源码,是有参数的,而且声明了 static

public static String toString(int[] a) {
    if (a == null)
        return "null";
    int iMax = a.length - 1;
    if (iMax == -1)
        return "[]";

    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; ; i++) {
        b.append(a[i]);
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}
复制代码

2. 为什么自带的二分法,如果一个数找不到,返回的索引是 -6 呢?

这个时候我们就可以去看一眼源码一窥真相。

二分查找的源码:

private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                 int key) {
    int low = fromIndex;
    int high = toIndex - 1;

    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = a[mid];

        if (midVal < key)
            low = mid + 1;
        else if (midVal > key)
            high = mid - 1;
        else
            return mid; // key found
    }
    return -(low + 1);  // key not found.
}
复制代码

然后你就会发现在最后一行:没找到的话,默认取了左边最靠近的索引+1,再取负数。

而且还有一个地方非常的细节,二分法取中间的话,源码用了位移的操作,没有写公式,有效的防止了溢出。(关于二分法的更多内容,可以阅读这篇「如何优雅的实现二分查找」:juejin.cn/post/701598…

我犯的非常简单的错误:

在类里包了其他类,导致类型报错;

没有 main 方法,就写 System.arraycopy,也报错了。

猜你喜欢

转载自juejin.im/post/7017465528943902727
今日推荐