基础知识
很多道理往往可以用简单的话说明白。 关于 Java 数组,你只需要记住两句话:
1. 数组是相同类型数据的有序集合;
2. 数组也是对象。
展开说说:
- 长度确定且不可改;
- 类型不可改;
- 类型可基本可引用;
- 数据的变量属于引用类型,数组也是对象,数据的元素相当于对象的属性。
Java 数组初始化的三种方式:
- 静态初始化:一开始就把值给好了;
- 动态初始化:一开始给个长度,然后再逐个赋值;
- 默认初始化:动态初始化前一步,然后就用这个系统默认给的值:0、0.0、false、null。
练习点:
- Array.toString([]);
- System.arraycopy(原数组, 原数组开始的索引, 要拷贝到的数组, 目标数组开始拷贝的索引, 从原数组拷贝的长度);
- for(type i: array) 来逐个遍历;
- 三种初始化方法;
练习代码如下:
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)); } }
运行结果如下图:
查看源码的技巧:
在 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,再取负数。
而且还有一个地方非常的细节,二分法取中间的话,源码用了位移的操作,没有写公式,有效地防止了溢出。