菜鸡的Java笔记 第七 - java 数组
数组的基本概念 笔试中经常出现的试题或是问题
1.1 概念
数组指的是一组相关变量的集合
如果用最原始的方式定义100个变量的话没问题但是这些变量的关联实在是太麻烦了
在JAVA 中数组属于引用数据类型 既然是引用数据类型就牵扯到内存的关系。
对于数组的定义语法有以下两种形式
声明并开辟数组;
数组类型 数组名称 [] = new 数组类型[长度];
数组类型 [] 数组名称 = new 数组类型[长度];
分步完成;
声明数组: 数组类型 数组名称 [] = null; 数组类型 [] 数组名称 = null;
开辟数组: 数组名称 = new 数据类型 [];
当数组开辟空间之后那么就可以采用“数组[索引]”的形式进行数组的访问
但是需要注意的是,如果现在数组的长度为3,那么索引的范围是 0~2 (一共3个元素)
如果操作中超过了数组的允许索引范围,则程序在运行过程之中会出现(数组越界)
现在是动态初始化 动态初始化的特点 是数组开辟空间之后,数组中每个元素的内容都是其对应数据类型的默认值
数组本身是一种顺序式的结构,所以进行数组内容输出的时候,往往可以采用循环的方式完成
由于数组的长度是固定的,所以只要是进行数组的输出那么都会考虑使用for循环这里面就牵扯到了一个数组长度的取得,在JAVA中可以使用“数组对象.length”,属性取得
//实现数组循环输出
public class array(){ // 程序必须有类
public static void main(String args){
// 定义数组
int data [] = new int[3]; // 开辟了一个data数组,长度为3
Systme .out.println(data.length);
data[0] = 10; // 为数组赋值
data[1] = 20;
data[2] = 30;
for(int x = 0;x<data.length;x++){
// 通过循环来控制索引
Systme.out.println(data[x]+","); //数组名称[索引]
}
}
}
数组引用分析
引用数据类型的分析过程几乎都是一样的,所以数组的引用分析其本质也是一样的,与对象的流程是相同的
唯一的区别是在于普通的类对象是把保存属性,利用属性名称来操作,但是数组保存的是一组内容,利用索引来操作
那么既然此关系可以弄明白 所谓的分步的操作也是就是一样的过程
public class array1(){// 程序必须有累
public static void main(String args[]){
int data[] = new int[3];//开辟了一个data数组,长度为3
// 只有声明的时候加上“[]”
data[0] = 10; // 为数组赋值
data[1] = 20;
data[2] = 30;
int temp [] = data; // 引用
temp[0] = 100; // 引用赋值
System,out,println(data.length);
}
}
数组的静态初始化
上一课是动态数值的操作讲解,动态初始化操作的特点在于其只能够在开辟数组空间之后进行数组内容的一个赋值
如果现在希望数组开辟之后就可以存在明确的内容,那么则可以使用数组的静态初始化
语法如下
简化型;
数据类型 数组名称 [] = {值,值,值。。。。。。}
数据类型 [] 数组名称 = {值,值,值。。。。。。}
完整型;(推荐使用)
数据类型 数组名称 [] = new 数据类型[]{值,值,值。。。。。。}
数据类型 [] 数组名称 = new 数据类型[]{值,值,值。。。。。。}
public class stete(){ // 静态
public static void main(String args[]){
int data[] = new int[]{10,20,30}; // 数组静态初始化
for(int x = 0,x<data.length;x++){
System.out.println(data[x]+"."):
}
}
}
// 范例;判断某一个数字是否在数组中存在?
public class stete(){ // 静态
public static void main(String args[]){
int sdata = 11; // 要查找的数据
boolean flag = false; // 保存查找结果,如果找到了修改为true
int data[] = new int[]{10,20,30,11,22,33}; // 数组静态初始化
for(int x = 0,x<data.length;x++){
if(data[]==sdata){ // 现在已经查找到内容
flag = true;
break; // 退出循环
}
}
if(flag){
System.out.println("该数据已经查找到!"):
}else{
System.out.println("该数据没有查找到!"):
} }
}
但是严格来讲现在这个代码性能并不好,因为他需要将数组中的每一个元素都进行判断
面试题;请解释什么叫二分查找法(折半查找法(log2n))
二分查找法的重要支持;数组中的数据必须是有序的
二维数组
在开发之中,之前使用的数组只有一个索引下标,所以可以简单的将其理解为是一个一维数组。一维数组的特点是可以根据一个索引号确定内容
二维数组实际上与数据表的形式是完全相同的,有行和列组成,那么想要确认一个数据,必须有行和列的编号
对于二维数组的定义有两种语法结构;
动态初始化;
数据类型 数组名称[][] = new 数据类型[行个数][列个数];
静态初始化;
数据类型 数组名称 [][] = new 数据类型[][]{
{数据,数据,数据......}
{数据,数据。数据......}
}
实际上可以发现二维数组的本质就是在数组里面继续嵌套了其他的数组
public class twoarray(){
public static void main(String args[]){
int data [][] = new int[][]{
{1,2}
{4.5,6}
{7,8,9,10}
};
for(int x = 0;x<data.length;x++){ // 控制数组行
for(int y = 0;y<data[x],length;y++){
System.out.println(data[x][y]+","
)
}
System.out.println():
}
//面试题;实现二维数组转置(转置;行变列,列变行)(这都属于数组的逻辑控制,用于扩充大脑思维)
for(int x = 0;x<data.length;x++){
for(int y = 0;y<=x;y++){
if(x!=y){
int temp = data[x][y];
data[x][y] = data[y][x];
data[y][x] = temp;
}
}
System.out.println():
}
for(int x = 0;x<data.length;x++){ // 控制数组行
for(int y = 0;y<data[x],length;y++){
System.out.println(data[x][y]+","
)
}
System.out.println():
}
System.out.println():
}
}
/* 转置
public class Dtada{
public static void main (String args[]){
intdata [] = new int[]{1,2,3,4,5,6};
reverse(data);
printArray(data);
}
public static void reverse(int temp []){ // 返回数组
int center = temp.length / 2; //计算转换次数
int head = 0;
int tail = temp.length - 1;
for(int y = 0;y<center; y++){
int tempData = temp[head];
temp[head] = temp[tail];
temp[tail] = tempData;
head ++ ;
tail -- ;
}
}
public static void printArray(int temp[]){ //该方法要接收一个
for(int x = 0;x<temp.length; x++){
System.out.println(temp[x] + ",");
}
System.out.println();
}
}
数组与方法
在数组与方法进行传递的操作过程之中,实际上就是属于引用传递。
在数组与方法间的操作中主要考虑两种形式方法接收数组,另外一种就是方法返回数组。
不管是接收还是返回,最终操作的一定是一个堆内存的使用
public class arrayAndMethod{
public static void main(String args[]){
int [] data = new int[]{1,3,5,7,9}: // 数组
printArray(data): // int temp[] = data:
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
// 整个的操作过程与数组的引用接收是完全一样的 但是这个时候的代码只是针对于 当前的数组内容进行了简单的输出。
// 于是下面可以进一步的加强,例如:设置一个方法,在次方法之中实现数据的乘2操作
/* 方法里面修改数组内容
public class arrayAndMethod{
public static void main(String args[]){
int [] data = new int[]{1,3,5,7,9}: // 数组
printArray(data): // int temp[] = data:
}
public static void inc(int arr[]){ // 负责数组内容的改变
for(int x = 0:x<arr.length:x++){
arr[x]*=2: //arr[x] = arr[x]*2: //数组中的每个元素乘2后保存
}
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
// 在大部分情况下,如果某一个方法可以接收的数据类型是引用数据类型,那么往往都不需要设置返回值
// setName(String name) 返回的是 void
/* 范例:数据排序操作(理解)
面对数组中发现可以保存有多个数据,但是在很多时候(例如:二分查找法)
那么必须针对于数组中的数据进行排序,所以这个时候就需要进行一些复杂的处理
public class arrayAndMethod{
public static void main(String args[]){
int data [] = new int[]{19,8,37,6,55,4,73,2,91,0}:
for(int x = 0:x<data.length - 1:x++){ // 再加一个循环 一次循环是不够的
for(int y = 0:y<data.length - 1:y++){ -1 防止越界异常
if(data[y]>data[y+1]){
int temp = data[y]:
data[y] = data[y+1]:
data[y+1] = temp:
}
}
System.out,println("第"+ x +"次排序:"):
printArray(data):
}
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
分析;
第1次排序.8.19.6.37.4.55.2.73.0.91
2. 8.6.19.4.37.2.55.0.73.91
3 6.8.4.19.2.37.0.55.73.91
4 6.4.8.2.19.0.37.55.73.91
5 4.6.2.8.0.19.37.55.73.91
6 4.2.6.0.8.19.......
7 2.4.0.6.8.19......
8 2.0.4.6.8
9 0.2.4.6.8......
通过分析可以发现 排序并不是一次完成的,而是需要多次,也就是说至少需要“数组长度-1次”
此时是已实现了排序操作的要求。但非常遗憾的是,这个代码里面主方法的代码太多了
主方法本身就是一个日后程序调用的客户端,所以客户端的操作代码中不应该编写过多的复杂操作,应该将代码进行简化处理
public class arrayAndMethod{
public static void main(String args[]){
int data [] = new int[]{19,8,37,6,55,4,73,2,91,0}:
sort(data): // 客户端调用越简单越好
printArray(data):
}
public static void sort(int arr){ // 单独完成了一个数组的排序操作
for(int x = 0:x<arr.length - 1:x++){ // 再加一个循环 一次循环是不够的
for(int y = 0:y<arr.length - 1:y++){ -1 防止越界异常
if(arr[y]>arr[y+1]){
int temp = arr[y]:
arr[y] = arr[y+1]:
arr[y+1] = temp:
}
}
System.out,println("第"+ x +"次排序:"):
printArray(data):
}
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
面试题请编写一个数组排序操作 (以上就是答案)
/* 范例:数组的反转操作
就是将一个数组实现首尾交换,但是交换的实现方式有两种
第一种实现思路:
定义一个新的数组,而后将原始数组的内容进行逆序输出。随后改变原始数组的引用
public class arrayAndMethod{
public static void main(String args[]){
int data [] = new int[]{19,8,37,6,55,4,73,2,91,0}:
int newArr[] = new int[data.length]: // 声明一个与原始数组大小相同的数组
int foot = data.length -1: // 定义原始数组的操作脚标
for(int x = 0:x<newArr.length:x++){
newArr[x] = data[foot--]: // 逆序保存
}
data = newArr: // 改变原始数组引用
printArray(data):
} public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
以上的代码虽然可以实现转置,但是会产生垃圾,而我们开发的原则,应该是产生越少的垃圾越好
第二种实现方式:在一个数组上实现转置(计算公式:数组长度\2)
public class arrayAndMethod{
public static void main(String args[]){
int data [] = new int[]{19,8,37,6,55,4,73,2,91,0}:
reverse(data):
printArray(data):
}
public static void reverse(int arr[]){
int center = arr.length/2:
int head = 0:
int tail = arr.length - 1:
for(int x = 0:x<center:x++){
int temp = arr[head]:
arr[head] = arr[tail]:
arr[tail] = temp:
head ++:
tail --:
}
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
以上都是方法接收数组的形式,下面再来看一下方法返回数组的操作,如果某一个方法要返回一个数组,只需要将方法的返回值类型声明为数组即可
范例:方法返回数组
public class arrayAndMethod{
public static void main(String args[]){
int data [] = init(): printArray(data):
}
public static void int []init(){
return new int[]{19,8,37,6,55,4,73,2,91,0}: // return null: 也是没有问题的
}
public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
如果返回的是引用数据类型,那么返回null语法上是没有任何问题的
/* 对象数组
对象数组的使用,以及内存的分配操作
对象数组的核心概念;某一个数组之中的保存的都是对象,所以对于对象数组的定义格式有以下两种
动态初始化:类名称 对象数组名称[] = new 类名称[长度]:
静态初始化:类名称对象数组名称 [] = new 类名称[]{实例化对象,......}
范例:使用动态初始化定义对象数组
cladss Object{
private String name:
private int age: public Object(String n,int a){
name = n:
age = a:
}
// 无参构造 setter getter 省略
public String getlnfo(){
return"姓名"+neme+",年龄"+age:
}
}
public cladss objectArray{ // 程序必须有类
public static void main(Stirng args[]){
Object per [] = new Object[3]: // 开辟了一个包含有三个元素的对象数组
for(int x = 0:x<per.length:x++){
System.out.println(per[x].getlnfo):
}
}
}
使用动态初始化操作形式产生的对象数组,里面的每一个元素都是null(累是引用数据类型)
添加数据:
public cladss objectArray{ // 程序必须有类
public static void main(Stirng args[]){
objectArray per [] = new objectArray[3]:
// 开辟了一个包含有三个元素的对象数组
per[] = new Object("小三",10):
per[] = new Object("小四"12):
per[] = new Object("小五",15):
for(int x = 0:x<per.length:x++){
System.out.println(per[x].getlnfo):
}
}
}
累本身属于引用数据类型,那么所有的对象一定都会保存在对内存空间,而对象数组包含的是一组对象
除了动态初始化之外也可以进行静态初始化的操作
范例:静态初始化对象数组
public cladss objectArray{ // 程序必须有类
public static void main(Stirng args[]){
objectArray per [] = new objectArray[3]: // 开辟了一个包含有三个元素的对象数组
Object perA = new Object("小三",10):
Object perB = new Object("小四",12):
Object perC = new Object("小五",15):
Object per [] = new Object[]{perA,perB,perC}:
for(int x = 0:x<per.length:x++){
System.out.println(per[x].getlnfo):
}
}
}
第二种
public cladss objectArray{ // 程序必须有类
public static void main(Stirng args[]){
objectArray per [] = new objectArray[3]: // 开辟了一个包含有三个元素的对象数组
Object per [] = new Object[]{
new Object("小三",10),
new Object("小四",12),
new Object("小五",15)}:
for(int x = 0:x<per.length:x++){
System.out.println(per[x].getlnfo):
}
}
}
/* 总结
有了对象数组的概念之后实际上就是相当于简单JAVA类的概念有进一步进行了提升
如果是基本数据类型,则数组里面只保存数据,而如果保存了对象 那么每个元素可以保存更多的内容
但是数组永远都有自己的缺陷 长度是固定的
*/
/* 与数组有关的类库
java 本身提供有一系列的开发类库帮助用户进行代码编写,那么下面首先给出两个基本的数组操作方法
1.数组拷贝:一下的语法与原始定义有出入,以后在细化;
拷贝:System.arraycopy(原始数组,原始数组开始点,目标数组,目标数组的开始点,拷贝长度):
范例:数组拷贝
原始数组1:1,2,3,4,5,6,7,8,9
原始数组2:10,20,30,40,50,60,70,80,90
希望实现数组2部分内容替换掉数组1的内容:1,60,70,80,5,6,7,8,9
public class classLobraries{
public static void main(String args[]){
int data1[] = new int[]{1,2,3,4,5,6,7,8,9}:
int data2[] = new int[]{10,20,30,40,50,60,70,80,90}:
System,arraycopy(data2,5,data1,1,3):
printArray(data1):
}
}
/* 数组排序
语法:java.util.Arrays.sort(数组名称):
范例:数组排序
public class arrayAndMethod{
public static void main(String args[]){
int data[] = new int []{89,10,20,1,0,2,8,3,90,67,9,7}:
java.util.Arrays.sort(data):
printArray(data): public static void printArray(int temp[]){ // 接收一个数组
for(int x = 0:x<temp.length:x++){
System.out.println(temp[x]+"."):
}
System.out.println():// 换行
}
}
这种方式是在代码实际开发中使用的,千万要记住别在面试里完成
/*总结
1,数组属于引用数据类型
2,数组属于线性的存储结构,里面的内容可以根据索引线性操作
3,数组里面容易出现面试题
*/
菜鸡的Java笔记 第七 - java 数组的更多相关文章
- Java笔记(七)
File类: import java.io.File; import java.io.IOException; public class Demo{ public static void main(S ...
- 【Java笔记】配置文件java.util.Properties类的使用
配置文件的路径:项目名/src/main/resources/mmall.properties mmall.properties的内容是键值对.例如假设写了ftp服务器的一些信息. ftp.serve ...
- Java笔记12:Java对象排序
代码: import java.util.Arrays; import java.util.Comparator; class Person { private String name; privat ...
- JAVA笔记4__static关键字/对象数组/foreach/方法的可变参数
/** * static关键字:修饰属性(实质就是全局变量).方法(无需本类的对象即可调用此方法).类. * 1.static方法只能调用static方法 * 2.static方法只能访问static ...
- 菜鸡的Java笔记 第四 - java 基础运算符
数学运算符,逻辑运算,三目运算,位运算 double d2 = 314e2; //采用科学计数法的写法,表示10的2次方.= 31400.0 代码写的越简单越好 简化运算符 代码:x=x+y 可以 ...
- 菜鸡的Java笔记 第二十三 - java 抽象类的概念
abstractClass 抽象类的概念 1.抽象类的基本定义 2.抽象类的使用原则 不会抽象类与接口,java = 没学 ...
- 菜鸡的Java笔记 第八 - java 面向对象
面向对象的特点以及开发过程. java中最大的特点是其支持面向对象编程设计思想.在面向对象之前广泛流传的是面向过程的编程思想,例如:C语言的开发就属于面向过程 如果要想更简单的去理解面向过 ...
- 菜鸡的Java笔记 第六 - java 方法
前提:现在所讲解的方法定义格式,只属于JAVA 方法定义的其中一种组成方式.而完整的组成方式将随着学习逐步渗透. 1.方法的基本定义 方法(Method)在一些书中也会有人将其说是 函数(Funct ...
- 菜鸡的Java笔记 第五 - java 程序逻辑控制
程序主要分为三种逻辑:顺序,分支,循环. if 分支语句 if分支语句是最为基础的分支操作,但是其有三种使用形式: if语句 if.....else 语句 if....else...if...el ...
随机推荐
- AOJ/树与二叉搜索树习题集
ALDS1_7_A-RootedTree. Description: A graph G = (V, E) is a data structure where V is a finite set of ...
- NOIP 模拟四 考试总结
#T1随 又是liu_................... 数列n,m个操作,每次随机取a[i],x=x*a[i]%k; 问题是求x期望%mod; 首先考虑到期望转移过程中存在%k,一般套路线性期望 ...
- 10.8 location
创建一个前台站点 server { listen 80; server_name www.nginx.com; locaiton / { root /var/www/html/www; } } 创建一 ...
- 基于Tesseract组件的OCR识别
基于Tesseract组件的OCR识别 背景以及介绍 欲研究C#端如何进行图像的基本OCR识别,找到一款开源的OCR识别组件.该组件当前已经已经升级到了4.0版本.和传统的版本(3.x)比,4.0时代 ...
- 题解 最长道路tree
题目传送门 题目大意 给出一个\(n\)个点的树,每个点有点权,定义一条链的贡献为该链的点数乘上链上的权值和,求出树上所有链中的权值最大值. \(n\le 5\times 10^4\) 思路 算是我入 ...
- 云原生的弹性 AI 训练系列之三:借助弹性伸缩的 Jupyter Notebook,大幅提高 GPU 利用率
Jupyter Notebooks 在 Kubernetes 上部署往往需要绑定一张 GPU,而大多数时候 GPU 并没有被使用,因此利用率低下.为了解决这一问题,我们开源了 elastic-jupy ...
- redis分片集群安装部署
redis分片集群安装与部署 分片集群的优势 高可用.且方便扩展. 数据分片,多节点提供服务,提高性能,数据提供冗余备份. 分片集群部署 只需更改配置文件 部署架构:6个节点,3主3从.数据集分为3片 ...
- Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战
一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...
- 最详细的Android SDK下载安装及配置教程-------全文均为引用
<https://www.cnblogs.com/gufengchen/p/11038029.html>
- 指标统计:基于流计算 Oceanus(Flink) 实现实时 UVPV 统计
作者:吴云涛,腾讯 CSIG 高级工程师导语 | 最近梳理了一下如何用 Flink 来实现实时的 UV.PV 指标的统计,并和公司内微视部门的同事交流.然后针对该场景做了简化,并发现使用 Flink ...