基础知识
很多道理往往可以用简单的话说明白。 关于 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,再取负数。
而且还有一个地方非常的细节,二分法取中间的话,源码用了位移的操作,没有写公式,有效地防止了溢出。