目录:
- 1.数组
- 2.数组的 “存储结构”
- 3.数组的优缺点:
- 3.1 数组的优点
- 3.2 为什么数组的检索效率高?
- 3.3 数组的缺点
- 4.一维数组
- 4.1 一维数组的“存储结构”
- 4.2 一维数组的“静态初始化”
- 4.3 一维数组的“动态初始化”
- 4.4 一维数组的“遍历”
- 5.数组的“扩容”
- 6.二维数组
- 61. 二维数组
- 6.2 二维数组的“遍历”
- 7.Arrays工具类:
- String toString( T [ ] array )
- void sort( T [ ] array )
- void sort( T[ ] a , Comparator<? super T> c) (降序排列)
- int binarySearch( T[ ] array, T key)
- int binarySearch( T[ ] array , int fromIndex, int toIndex, T key)
- void fill( T[ ] array, T value)
- void fill( T[ ] array, int fromIndex, int toIndex, T value)
- boolean equals (T[ ] array1, T[ ] array2)
- T[ ] copyOf( T[ ] original, int newLength)
- T[ ] copyOfRange( T[ ] original, int fromIndex, int toIndex)
1.数组
- 数组是一种引用数据类型。不属于基本数据类型,因而数组对象是存储在堆内存中。 数组的父类是Object。
- 数组实际上是一个容器,可以同时存储 (引用数据类型) 多个数据/元素。或者 也可同时存储 (基本数据类型) 多个数据/元素。(数组是“一组数据”的集合。)
- 数组当中如果存储是“Java对象”的话,实际上存储的是对象的引用 / 对象的内存地址。
- 数组一旦创建,长度不可变。
- 所有数组对象都有length属性 (Java自带的),用来获取数组中元素的个数。
- 数组的分类:一维数组、二维数组、三维数组、多维数组。
2.数组的 “存储结构”
- 数组在内存中进行存储时,数组元素的内存地址是连续/相连 的。
(存储中的元素都是有规则的,挨着排列的,内存地址连续 )- 数组中第一个元素的“内存地址” 就是这个数组对象的内存地址。
- 数组中每一个元素都是有下标的,以1递增,最后一个元素的下标是length-1。
3.数组的优缺点:
3.1 数组的优点
- 查询/查找/检索某个下标的元素时效率极高,是查询效率最高的一个数据结构。
- 数组的检索效率高。
3.2 为什么数组的检索效率高?
- 每一个元素的内存地址在空间存储上是连续的,数组中每一个元素类型相同、占用空间大小一样。
- 如果知道第一个元素的内存地址,可通过下标 + 数学表达式计算出某个下标元素的内存地址,直接通过内存地址定位元素,所以数组的检索效率最高。
(数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的,因为数组中元素查找时不会一个一个找,是通过数学表达式算出来的)
3.3 数组的缺点
- 由于为了保证数组每个元素的的内存地址连续,所以在数组随机删除或增加元素时,效率较低,因为随机删除元素会涉及到后面元素统一向前或向后位移的操作。
- 数据不能存储大数据量,因为很难在内存空间上找到一块特别大的且连续的内存空间。
- 注意:
对于数组中最后一个元素的增删,是没有效率影响的。
4.一维数组
4.1 一维数组的“存储结构”
4.2 一维数组的“静态初始化”
//声明一个int类型的数组,使用静态初始化的方式
int[] a = {1, 100, 200, 300, 400, 500};
//所有数组对象都有length属性
System.out.println("数组中元素个数为: "+a.length);
//数组中每一个元素都有下标,通过下标对数组中的元素进行存和取
//取(读)
System.out.println("数组中第一个元素: "+a[0]); // 1
System.out.println("数组中最后一个元素: "+a[a.length-1]); // 500
//存(改)
//把第一个元素改为123
a[0] = 123;
//把最后一个元素改为111
a[a.length - 1] = 111;
4.3 一维数组的“动态初始化”
- int [ ] arr =new int[5] ; //这里的5表示元素个数。 初始化一个5个长度的int类型数组,每个元素默认值为0。
- String [ ] names = new String[6] ; //初始化6个长度的String类型数组,每个元素默认值为null。
- 例子如:
/** * 数据类型 默认值 * ---------------- * byte 0 * short 0 * int 0 * long 0L * float 0.0F * double 0.0 * boolean false * char \u0000 * 引用数据类型 null */ //动态创建一维数组 int [] a = new int[4]; //创建一个长度为4的int数组,数组中的默认值为0 //遍历数组 for (int i = 0; i < a.length;i++) { System.out.println(a[i]); }
4.4 一维数组的“遍历”
//声明一个int类型的数组, “静态初始化” 一维数组
int[] a = {1, 100, 200, 300, 400, 500}; //下标0-5
//一维数组的遍历
// a.length =6 (数组长度/数组元素 : 6) , 下标最大为5
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]); //i是下标,从0到5
}
/**
* 从最后一个元素遍历到第一个元素
* 数组长度为: a.length : 6 (6个元素)
* 下标最大长度为: a.length-1 : 5 (因为下标是从0开始的,0 1 2 3 4 5 : 此时就已有6个元素,所以下标最大长度为5)
*/
for (int i=a.length-1; i>=0; i--) {
System.out.println("颠倒顺序输出:"+ a[i]); //i是下标,从0到5
}
/**
* 这段代码会报错
*
* 下标为6表示第7个元素,a[]数组中下标只能到5(只有6个元素)
*/
System.out.println(a[6]); //“数组下标越界” 异常
5.数组的“扩容”
Java中 数组的扩容:先新建一个大容量的数组,然后将小容量的数组中的数据一个一个拷贝到大数组中。
数组扩容效率较低,因为涉及到 数组的拷贝。
例子如:
//数组的扩容/数组的拷贝 //拷贝源 (从这个数组进行拷贝) int[] src = {1, 2, 3, 4, 5}; //拷贝目标 (拷贝到这个数组上) int[] dest = new int[20]; //动态初始化数组 //调用JDK System中的 arraycopy()方法,完成数组的拷贝 /** * 参数代表的含义分别为: 拷贝源、开始拷贝的下标、拷贝目标、拷贝到的数组的下标、拷 * 的长度/数量 */ System.arraycopy(src, 1, dest, 3, 2); //拷贝数组中所有数据 System.arraycopy(src, 0, dest, 0, src.length); for (int i = 0; i < dest.length; i++) { System.out.println(dest[i]); }
6.二维数组
61. 二维数组
- 二维数组是是一个“特殊的一维数组”, 二维数组中每一个元素都是“一个一维数组”。
- a[二维数组中的一维数组的下标][一维数组的下标]
- a[一维数组的下标][一维数组中元素的下标]
/** * 关于二维数组的: 读和改 * a[二维数组中的一维数组的下标][一维数组的下标] * a[一维数组的下标][一维数组中的元素的下标] * a[0][0] :表示第一个一维数组中的第一个元素。 * a[3][100] :表示第四个一维数组中的第101个元素。 */ public class ArrayTest3 { public static void main(String[] args) { //二维数组 int [][] a ={ {34,4,65}, {100,200,300},{0}}; //获得二维数组中的 “第一个一维数组” int[] a1 = a[0]; //获得二维数组中的 “第一个一维数组中的第一个元素” int a2 =a[0][0]; System.out.println(a2); } }
6.2 二维数组的“遍历”
public class ArrayTest3 {
/**
* a[一维数组的下标][一维数组中的元素的下标]
* 第一个[]:负责遍历二维数组
* 第二个[]:负责遍历一维数组
*/
public static void main(String[] args) {
//二维数组
String[][] array ={
{"张三","李四","王五"},
{"Java","python","php","C++"},
{"Jack","roe","jack"}
};
//遍历二维数组
for (int i = 0; i < array.length; i++) {
//负责遍历一维数组
//a[二维数组中的一维数组的下标][一维数组中的元素的下标]
for (int j = 0; j < array[i].length;j++) {
//遍历一维数组中的具体的元素
//输出二维数组中的每一个一维数组中的每一个元素
System.out.println(array[i][j]);
}
}
}
}
7.Arrays工具类:
String toString( T [ ] array )
String toString( T [ ] array ):将数组转换为字符串。
该方法将数组的内容以字符串的形式返回,这个字符串中元素用逗号分隔,最外层用[ ]包裹。
如: [“123”,“12345”]String toString( T [ ] array )可用于任何类型的数组,包括基本数据类型和引用数据类型。
例子如 :
Integer[] numbers = { 5, 2, 8, 1, 7 }; String[] s = {"123", "HelloWorld"}; char[]c = {'a', 'b', 'c'}; double[] f = {12.123, 13.14}; System.out.println(Arrays.toString(numbers)); // [5, 2, 8, 1, 7] System.out.println(Arrays.toString(s)); // [123, HelloWorld] System.out.println(Arrays.toString(c)); // [a, b, c] System.out.println(Arrays.toString(f)); // [12.123, 13.14]
void sort( T [ ] array )
void sort( T [ ] array ):
对数组中的数据进行 升序排序。Integer[] numbers = { 5, 2, 8, 1, 7 }; // [5, 2, 8, 1, 7] System.out.println("排序前的数组: " + Arrays.toString(numbers)); //升序排列 Arrays.sort(numbers); // [1, 2, 5, 7, 8] System.out.println("排序后的数组: " + Arrays.toString(numbers));
void sort( T[ ] a , Comparator<? super T> c) (降序排列)
- void sort( T[ ] a , Comparator<? super T> c):
使用自定义比较器对 “数组中数据”进行 降序排序。/** * 使用 “自定义比较器” 降序排列 */ Integer[] numbers = {6, 2, 8, 1, 50}; //静态初始化 Arrays.sort(numbers, new Comparator<Integer>() { @Override public int compare(Integer num1, Integer num2) { return num2 - num1; // 降序排列 } }); // Arrays.toString() : 将"数组" 转换为 “字符串” System.out.println(Arrays.toString(numbers)); // [50, 8, 6, 2, 1]
int binarySearch( T[ ] array, T key)
binarySearch( T[] array, T key) :
在 有序数组 中使用二分查找算法来查找 指定元素的索引位置/下标值。 该方法返回为该指定元素的索引值 或 (-(插入点) -1 )。它可以应用于各种基本类型数组和对象类型数组。使用该方法的前提是:该数组是有序的,可用 sort(int[ ]) 方法排序。
如果指定元素在数组中,则返回该元素的索引值。
如果指定元素 不在数组中,则返回 (-(插入点) -1 )。插入点被定义为:将键插入到数组的那一点,即第一个大于此键的元素索引。 如果数组中所有元素都小于指定的键,则为 a.length。
(可以理解为当指定元素(key)不在数组中时,有序插入到数组中,如果该key后面有元素时,插入点为: 大于key 的第一个元素的索引值; 如果数组中所有元素都小于key,则插入点为: a.length)注意:
这保证了当且仅当此键被找到时,返回的值将>=0例子如:
int[] numbers = {2, 4, 8, 12, 40, 70,90}; int key = 8; int key1 = 1; int key2 = 100; int key3 = 50; int key4 = 70; int key5 = 100; int key6 = 130; int key7 = -1; /** * binarySearch : 在"有序数组"中查找“指定元素”的“索引值/下标值” * 返回值为该"指定元素"的索引值 或 “(-(插入点)-1)” */ System.out.println(Arrays.binarySearch(numbers, key)); // 2 System.out.println(Arrays.binarySearch(numbers, key1)); // -1 System.out.println(Arrays.binarySearch(numbers, key2)); // -8 System.out.println(Arrays.binarySearch(numbers, key3)); // -6 System.out.println(Arrays.binarySearch(numbers, key4)); // 5 System.out.println(Arrays.binarySearch(numbers, key5)); // -8 System.out.println(Arrays.binarySearch(numbers, key6)); // -8 System.out.println(Arrays.binarySearch(numbers, key7)); // -1 // key: 8 ---查找8在“有序数组”中的索引值 :2 int index = Arrays.binarySearch(numbers, key); if (index >= 0) { System.out.println("元素 " + key + " 在数组中的索引位置为 " + index); } else { System.out.println("元素 " + key + " 不在数组中"); }
int binarySearch( T[ ] array , int fromIndex, int toIndex, T key)
- 使用二分搜索法来搜索指定的数组的范围,以获得指定的值。
- 如果它包含在数组的指定范围内,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点 被定义为将键插入数组的那一点:即范围中第一个大于此键的元素索引,如果范围中的所有元素都小于指定的键,则为 toIndex。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。
void fill( T[ ] array, T value)
将数组的所有元素设置为指定的值。
String[] strs = {"hello","HelloWorld","中国"}; //字符串数组 //将数组的"所有元素"设置为"指定的值" Arrays.fill(strs,"123"); //Arrays.toString() : 将数组转换为字符串 String str = Arrays.toString(strs);//字符串 System.out.println(str); //[123, 123, 123]
void fill( T[ ] array, int fromIndex, int toIndex, T value)
将数组的指定范围内的元素设置为指定的值。
[fromIndex,toIndex) : 包括fromIndex,不包括toIndex。
例子如:
//字符串数组 String[] strs = {"hello","HelloWorld","中国","Java","python","C++"}; //将数组中“指定范围内的元素”设置为“指定的值” Arrays.fill(strs,1,4,"123"); //范围为: [1,4) ,不包括4 //Arrays.toString() : 将数组转换为字符串 String str = Arrays.toString(strs);//字符串 System.out.println(str); // [hello, 123, 123, 123, python, C++]
boolean equals (T[ ] array1, T[ ] array2)
boolean equals(T[] array1, T[] array2):比较两个数组是否相等。
String[] strs1 = {"Hello", "HelloWorld"}; String[] strs2 = {"Hello", "HelloWorld"}; String[] strs3 = {"Hello", "中国"}; boolean b1 = Arrays.equals(strs1, strs2); boolean b2 = Arrays.equals(strs1, strs3); System.out.println(b1); //true System.out.println(b2); //false
T[ ] copyOf( T[ ] original, int newLength)
T[ ] copyOf( T[ ] original, int newLength):复制指定长度的数组。
int[] array1 = {1, 2, 3, 4, 5,6,7,8,9,10}; int[] ints = Arrays.copyOf(array1, 5); //将数组转换字符串 String strs = Arrays.toString(ints); System.out.println(strs); //[1, 2, 3, 4, 5]
T[ ] copyOfRange( T[ ] original, int fromIndex, int toIndex)
T[ ] copyOfRange( T[ ] original, int fromIndex, int toIndex):复制部分数组。
[fromIndex , toIndex) : 包括初始索引,不包括最后索引。
int[] array1 = {1, 2, 3, 4, 5,6,7,8,9,10}; int[] ints = Arrays.copyOfRange(array1, 0, 6); // [0,6) //将数组转换字符串 String strs = Arrays.toString(ints); System.out.println(strs); //[1, 2, 3, 4, 5,6]