第十六章 数组
感觉这一章有点散,还是来说一下需要注意的点吧。
一、数组知识点
1、数组的初始化方式
①Integer[] array = {1, 2, 3}; ②Integer[] array = new Integer[10]; ③Integer[] array = new Integer[]{1,2,3};
数组分配空间,但是没有初始化,就是默认0值。
2、数组与容器的不同点
class Fruit {} class Apple extends Fruit {} Fruit[] f = new Apple[10]; List<Fruit> l = new ArrayList<Apple>();\\Error
数组进行这样的向上转型是合法的,而List这样转型不合法,因为List<Fruit>与ArrayList<Apple>根本不是子类与父类的关系。
3、数组是最高效的存储和随机访问对象引用的方式
4、length指的是数组的大小,而不是实际保存了多少元素。
5、数组中的每一维都可以有不同的长度
import java.util.Arrays; public class Demo1 { public static void main(String[] args) { Integer[][] array = new Integer[4][]; for(int i = 0; i < array.length; i++) { array[i] = new Integer[i+1]; System.out.println(Arrays.toString(array[i])); } System.out.println(Arrays.deepToString(array)); } }
输出结果:
[null]
[null, null]
[null, null, null]
[null, null, null, null]
[[null], [null, null], [null, null, null], [null, null, null, null]]
结果分析:Arrays类有创建数组可打印形式的静态方法。
Arrays.toString()创建一维数组的可打印形式。
Arrays.deepToString()创建多维数组的可打印形式。
二、Arrays类的实用方法
1、示例一:填充复制数组
mport java.util.Arrays; class Apple{} public class Demo2 { public static void main(String[] args) { Apple[] apple = new Apple[3]; Arrays.fill(apple, new Apple()); System.out.println(Arrays.toString(apple)); Integer[] a1 = new Integer[5]; Arrays.fill(a1, 88); Integer[] a2 = new Integer[10]; Arrays.fill(a2, 33); System.arraycopy(a1, 0, a2, 1, a1.length); System.out.println(Arrays.toString(a2)); } }
输出结果:
[arrays.Apple@edf4efb, arrays.Apple@edf4efb, arrays.Apple@edf4efb]
[33, 88, 88, 88, 88, 88, 33, 33, 33, 33]
结果分析:
fill():填充数组,从结果可以看出,填充对象时,是将同一对象的引用分配给每个元素。
System.arraycopy():复制数组,效率高。
2、示例二:数组的比较
import java.util.Arrays; public class Demo3 { public static void main(String[] args) { int[] a1 = new int[5]; int[] a2 = new int[10]; int[] a3 = new int[5]; Arrays.fill(a1, 12); System.arraycopy(a1, 0, a2, 0, a1.length); Arrays.fill(a3, 12); System.out.println("Arrays.equals(a1,a2): " + Arrays.equals(a1,a2)); System.out.println("Arrays.equals(a1,a3): " + Arrays.equals(a1,a3)); String[] s1 = new String[2]; Arrays.fill(s1, "Hi"); String[] s2 = {new String("Hi"), new String("Hi")}; System.out.println("Arrays.equals(s1,s2): " + Arrays.equals(s1,s2)); } }
输出结果:
Arrays.equals(a1,a2): false
Arrays.equals(a1,a3): true
Arrays.equals(s1,s2): true
结果分析:数组相等的条件是元素个数(length)相等,对应位置的元素也相等。数组的相等时基于内容的,一般来时,对象比较都是基于内容的。
3、示例三:元素的比较
方式一:实现java.lang.Comparable接口,使得类具有“天生”的比较能力。
方式二:创建一个实现了Comparator接口的单独类。
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; class CompType implements Comparable<CompType>{ String name; int age; CompType(String name, int age) { this.name = name; this.age = age; } public String toString() { return "[name = " + name + ", " + "age = " + age + "]"; } public int compareTo(CompType c) { return name.compareTo(c.name); } } class CompTypeComparator implements Comparator<CompType> { public int compare(CompType c1, CompType c2) { return c1.age < c2.age ? -1 : (c1.age == c2.age ? 0 : 1); } } public class Demo4 { public static void main(String[] args) { CompType[] c = new CompType[] {new CompType("Mike", 18), new CompType("Susan", 17), new CompType("Liu", 19)}; System.out.println("before sorting:"); System.out.println(Arrays.toString(c)); System.out.println("after sorting by name:"); Arrays.sort(c); System.out.println(Arrays.toString(c)); System.out.println("after reverse by name:"); Arrays.sort(c, Collections.reverseOrder()); System.out.println(Arrays.toString(c)); System.out.println("after sorting by age:"); Arrays.sort(c, new CompTypeComparator()); System.out.println(Arrays.toString(c)); } }
输出结果:
before sorting:
[[name = Mike, age = 18], [name = Susan, age = 17], [name = Liu, age = 19]]
after sorting by name:
[[name = Liu, age = 19], [name = Mike, age = 18], [name = Susan, age = 17]]
after reverse by name:
[[name = Susan, age = 17], [name = Mike, age = 18], [name = Liu, age = 19]]
after sorting by age:
[[name = Susan, age = 17], [name = Mike, age = 18], [name = Liu, age = 19]]
结果分析:Collections.reverseOrder()返回一个强制逆转自然顺序的比较器。
4、示例四:在已排序数组中查找
import java.util.Arrays; import java.util.Random; public class Demo5 { public static void main(String[] args) { Random rand = new Random(11); Integer[] array = new Integer[10]; for(int i = 0; i < array.length; i++) { array[i] = rand.nextInt(20); } Arrays.sort(array); System.out.println("sorted array:"); System.out.println(Arrays.toString(array)); while(true) { int key = rand.nextInt(); int location = Arrays.binarySearch(array, key); if(location >= 0) { System.out.println("Location of " + key + " is " + location); break; } } } }
输出结果:
sorted array:
[0, 7, 7, 8, 11, 13, 13, 13, 15, 18]
Location of 18 is 9
结果分析:
(1)先经过sort()排序才可以调用binarySearch(),否则结果是不确定的。
(2)binarySearch()必须和sort()使用同样的Comparator。
(3)Java标准类库针对正排序算法进行了特殊优化,针对基本类型设计“快速排序”,针对对象设计“合并排序”。