Java数组和数据存储
数组的定义
数组是相同类型数据的有序集合。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们。
数组的四个基本特点:
1.长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
2.其元素的类型必须是相同类型,不允许出现混合类型。
3.数组类型可以是任何数据类型,包括基本类型和引用类型。
4.数组变量属于引用类型,数组也是对象,数组中的元素相当于对象的属性!
创建数组和初始化
数组的声明方式(以一维数组为例)
1.type[ ] arr_name; //方式一
2.type arr_name[ ]; //方式二
注意事项
1.声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关。
2.声明一个数组的时候并没有数组真正被创建。
3.构造一个数组,必须指定长度。
初始化
数组的初始化方式总共有三种:静态初始化、动态初始化、默认初始化。
1. 静态初始化:除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。
int [ ] a = { 1, 2, 3 };// 静态初始化基本类型数组;
Man[ ] mans = { new Man(1, 1), new Man(2, 2) };// 静态初始化引用类型数组;
2.动态初始化:数组定义与为数组元素分配空间并赋值的操作分开进行。
int[ ] a1 = new int[2];//动态初始化数组,先分配空间;
a1[0]=1;//给数组元素赋值;
a1[1]=2;//给数组元素赋值;
3.数组的默认初始化:数组是对象,它的元素相当于对象的属性;每个元素也按照属性的方式被默认初始化。
int a2[ ] = new int[2]; // 默认值:0,0
boolean[ ] b = new boolean[2]; // 默认值:false,false
String[ ] s = new String[2]; // 默认值:null, null
数组常见操作
1.遍历指的就是“通过循环遍历数组的所有元素”。
2.拷贝指的是将某个数组的内容拷贝到另一个数组中.
数组的遍历
数组元素下标的合法区间:[0, length-1]。我们可以通过下标来遍历数组中的元素,遍历时可以读取元素的值或者修改元素的值。
for-each循环
for-each专门用于读取数组或容器中所有的元素。
使用增强for循环遍历数组
public class Test {
public static void main(String[ ] args) {
String[ ] ss = { "aa", "bbb", "ccc", "ddd" };
for (String temp : ss) {
System.out.println(temp);
}
}
}
for-each增强for循环在遍历数组过程中不能修改数组中某元素的值.
for-each仅适用于遍历,不涉及有关索引(下标)的操作。
数组的拷贝
System.arraycopy(object src,int srcpos,object dest, int destpos,int length)
该方法可以将src数组里的元素值赋给dest数组的元素,其中srcpos指定从src数组的第几个元素开始赋值,
length参数指定 将src数组的多少个元素赋给dest数组的元素。
java.util.Arrays类
Arrays类包含了:排序、查找、填充、打印内容等常见的数组操作。
多维数组
多维数组可以看成以数组为元素的数组。可以有二维、三维、甚至更多维数组,但是实际开发中用的非常少。最多到二维数组。
Comparable接口
多个对象做比较,就要有“比较规则”,然后实现排序。
事实上,java中排序算法的底层也依赖Comparable接口。
Comparable接口中只有一个方法:
public int compareTo(Object obj) obj为要比较的对象
方法中,将当前对象和obj这个对象进行比较,如果大于返回1,等于返回0,小于返回-1. (此处的1也可以是正整数,-1也可以是负整数)。
CompareTo方法的代码也比较固定:
public int compareTo(Object o) {
Man man = (Man) o;
if (this.age < man.age) {
return -1;
}
if (this.age > man.age) {
return 1;
}
return 0;
}
常见算法:冒泡排序、二分法查找(折半查找)
冒泡排序的基础算法:
重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来,这样越大的元素会经由交换慢慢“浮”到数列的顶端。
算法的运作如下:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
import java.util.Arrays;
public class TestBubbleSort {
public static void main(String[ ] args) {
int[ ] values = { 3, 1, 6, 8, 9, 0, 7, 4, 5, 2 };
bubbleSort(values);
System.out.println(Arrays.toString(values));
}
public static void bubbleSort(int[ ] values) {
int temp;
for (int i = 0; i < values.length; i++) {
for (int j = 0; j < values.length - 1 - i; j++) {
if (values[j] > values[j + 1]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
}
}
}
}
}
冒泡排序的优化算法
我们可以把上面的冒泡排序的算法优化一下,基于冒泡排序的以下特点:
1.整个数列分成两部分:前面是无序数列,后面是有序数列。
2.判断每一趟是否发生了数组元素的交换,如果没有发生,则说明此时数组已经有序,无需再进行后续趟数的比较了。此时可以中止比较。
import java.util.Arrays;
public class TestBubbleSort2 {
public static void main(String[ ] args) {
int[ ] values = { 3, 1, 6, 8, 9, 0, 7, 4, 5, 2 };
bubbleSort2(values);
System.out.println(Arrays.toString(values));
}
public static void bubbleSort2(int[ ] values) {
int temp;
for (int i = 0; i < values.length ; i++) {
// 定义一个布尔类型的变量,标记数组是否已达到有序状态
boolean flag = true;
/*内层循环:每一趟循环都从数列的前两个元素开始进行比较,比较到无序数组的最后*/
for (int j = 0; j < values.length - 1 - i; j++) {
// 如果前一个元素大于后一个元素,则交换两元素的值;
if (values[j] > values[j + 1]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
//本趟发生了交换,表明该数组在本趟处于无序状态,需要继续比较;
flag = false;
}
}
//根据标记量的值判断数组是否有序,如果有序,则退出;无序,则继续循环。
if (flag) {
break;
}
}
}
}
二分法检索(binary search)又称折半检索。
二分法检索的基本思想是设数组中的元素从小到大有序地存放在数组(array)中,首先将给定值key与数组中间位置上元素的关键码(key)比较,
如果相等,则检索成功;否则,若key小,则在数组前半部分中继续进行二分法检索;若key大,则在数组后半部分中继续进行二分法检索。
这样,经过一次比较就缩小一半的检索区间,如此进行下去,直到检索成功或检索失败。二分法检索是一种效率较高的检索方法。
import java.util.Arrays;
public class TestBinarySearch {
public static void main(String[ ] args) {
int[ ] arr = { 30,20,50,10,80,9,7,12,100,40,8};
int searchWord = 20; // 所要查找的数
Arrays.sort(arr); //二分法查找之前,一定要对数组元素排序
System.out.println(Arrays.toString(arr));
System.out.println(searchWord+"元素的索引:"+binarySearch(arr,searchWord));
}
public static int binarySearch(int[ ] array, int value){
int low = 0;
int high = array.length - 1;
while(low <= high){
int middle = (low + high) / 2;
if(value == array[middle]){
return middle; //返回查询到的索引位置
}
if(value > array[middle]){
low = middle + 1;
}
if(value < array[middle]){
high = middle - 1;
}
}
return -1; //上面循环完毕,说明未找到,返回-1
}
}