java逆流直上之数组
数组
1.初步了解数组的定义 int [] numbers=new int[100];初步了解对数组中元素的赋值、遍历数组、以及使用数组中元素;
2.数组的定义方式:
3.被定义的数组,可以求他的长度。格式为:数组名.length,所以在for循环,遍历数组的时候,长度就可以用这个(也是比较好的一种选择),这样的for循环具有可扩展性,如下图例子所示:
4.java中用new的方式定义了数组以后,数组的初始值已经被赋为0了,不需要再额外遍历,这是java的一个优势;
5.刚刚上面讲了,用new定义一个数组变量,数组的元素已经被初始化为0了;此外数组也可以不用new来定义,可以直接手动初始化赋值,格式如下:int [] numbers={12,12,13,14,15,16};此时系统会帮我自动数出数组的元素个数(可以用numbers.length检查一遍);
6.java数组变量定义的核心问题:我们不管是用new还是直接手动赋值定义出来的数组,数组本身都是在另外一个小角落呆着,而前面数组的名字(也就是我们定义的数组变量),都只是数组的管理者而非所有者,比如“int [] a=new int[100];”这里的a是数组管理者而非所有者,数组变量a具有对数组的管理作用,所以当我们有式子int [] b=a,那么就表示现在b和a都具有了对数组的管理作用,远处小角落里的数组,第一个数既是a[0],也是b[0],这点尤其重要,具体例子如下:输出结果为16;
7.接上一点,必须得出现类似于“int [] b=a;”这种类型的数组变量相互赋值的式子,才表示管理权的赋予与共同拥有;
8.要关注一下第四点:
数组变量之间的比较,也就是关系运算(比如a==b),是判断他们是否是同一个数组的管理者,如果是则结果为true,如果不是则结果为false;如下面这些例子:
【1】这个结果是true
【2】这个结果是false
【3】尽管两个数组内容相同,但是没有管理权限的交接式子,这仍然是两个不相同的数组,结果是false:
9.那么我们如何做到,将一个数组里面所有的元素拷贝到另外一个数组呢?
答:首先创立一个新的数组(new一下,长度可以是“旧数组.length”),然后使用遍历的方法来利用旧数组对新数组的元素,逐一拷贝和赋值;如下图代码所示:
数组计算
1.for-each循环的定义:假设我们定义了一个数组(变量)data,然后我们遍历数组的方法有常规的for循环“for(int i=0;i<data.length;i++),当然也有我们这里引入的for-each循环:
这里表示,读于数组data中的元素,循环的每一轮都赋值给k(k的类型要对),所以这里的k是会不断变化的。(for-each循环特别适合遍历数组的情形,但是不能知道位置,只能读取不能写,这是缺点,当然也不能用for-each循环来给数组赋值)。
//下面都是关于素数的运算
2.寻找素数:首先我们明白1和偶数(除了2)都是非素数,所以我们可以直接排除不去判断,然后现在只剩下3(你包括三)开始往后的奇数,判断他们是不是素数,现在就要然他们除以从3开始的奇数(也就是i=3开始,步进是2,因为奇数是不可能被2或2的倍数整除的),此时效率就提高了一倍,遍历的成本只有接近一半了,然后并且不需要遍历到接近所给数的最近的那个奇数,只需要遍历到sqrt(x)就可以了,这是数学知识可以课后再看,所以精简后的代码如下图所示:
注:上面还有部分代码已经排除了1和所有的非2偶数,math是java里带着的一个动东西,里面有一些函数;
3.构造素数表的方法,有两种:
【第一种,判断x是否是前面已知素数的倍数,如果是则是非素数,不是则计入数组,构造出素数表】
其中primes[cnt++]=x,可以分为两步"prime[cnt]=x; cnt++;"
【第二种方式:在给定的需要列出素数表的数值范围内,把已知的素数的倍数全部挑走(因为都是非素数),然后剩下的就是素数了,从而列出素数表】
二维数组
1.二维数组变量的定义和一维数组相似,可以用new进行初始化(初始化为0),也可以手动初始化,这时候要分为行和列,格式如下:
其实也并不一定要写成这种整整齐齐的矩阵的方式,写在一行中也是可以的,比“int [][]a={{1,2,3,4},{12,2,3,5},{1,4,7},};最后的一个逗号可以加上(也可以不加),加上是古老的传统;每行之间也是用逗号隔开;省略不写的话表示补零(这里参考下面对二维数组的初始化的专门的一点)。
2.二维数组的遍历,要用到双层的for循环,这里的条件可以很朴素的写行数和列数(或者用定义过的变量代替),也可以在表示行的for里写“数组名.length”,表示列的内层for里写“数组名[i].length”表示那一行的列数,具体写法如下图所示:
关于二维数组的定义和初始化
1.java中二维数组可以采取静态初始化的方式进行定义和赋值,格式比如:“ int[][] a={{1,2,3},{4,5},{6},}; ” 也就是我们在上面所说的手动赋值,上面我们搞错的内容是(已经标注出来了):在这种静态初始化定义下,系统不会帮我们自动补零,也就是说这形成的不是一个标准的矩阵。不会出现数组范围开大的情况,所以就不会出现系统将没赋值的位置初始值变为0的情况,开辟的数组空间与数组元素的多少有关,总之开辟的空间会正正好好,不多不少。如下图举例:
因此在这种定义的方式下,我们不能将其简单描述为一个三行三列的矩阵,如果我们想遍历数组,我们就不能简单的使用两重for循环比如:
【会出错的遍历方式,数组的下标溢出】
【正确的遍历方式,只能用上面讲的方法 数组名.length】
注意:a.length单纯是指二维数组a的行数,而每一行的列数则需要在for循环下使用a[i].length,这样遍历才不会出错!(这两种形式应该是固定的指行数和每行的列数,所以这里是先从行再到列);因为这两种形式是特指,所以我们应用的时候只能先行再列。
因此,我们有如下总结:对于标准的数组(标准的矩阵),我们知道行数和列数,我们可以使用两层for循环,先行再列或先列再行遍历数组,实现我们想要的功能。也能使用“数组名字.length表示行数,数组名字[i].length表示每一行的列数”先行再列的遍历数组,这种方法下没有办法先列再行。
对于不标准的数组(没有自动补零的数组),我们没有办法使用for循环进行遍历(不管是先行再列还是先列再行);我们只能用“数组名字.length表示行数,数组名字[i].length表示每一行的列数”先行再列的遍历数组,这种方式依然不能先列再行。
2.当然,在java中我们一般都是动态定义初始化,格式如下所示“int[][] a=new int[3][3];”此时会开辟3x3的空间,且每个位置上的元素值都会默认是0,不会缺省;当然也可以有如下定义(new int[x][]):
这样就用new定义了一个不规则的数组,且有元素的位置都是默认为0;