Go笔记··By/蜜汁炒酸奶

Java学Go入门笔记01-数组

该系列是在有Java基础上学习Go语言的一些基础的对比学习笔记。

数组

数组基础特点回顾:

  • 数组是一种线性数据结构。使用一组连续内存空间存储一组相同类型的数据。
  • 支持随机访问,按照下标访问数组中的元素的时间复杂度是O(1)。
  • 在数组中查找数据,即使是排好序的数组,使用二分查找,时间复杂度也只能达到O(logn)。
  • 插入和删除低效,因为需要维持连续的内存空间,在插入时需要在插入位置之后数组数据向后移动。删除时需要将被删位置之后的数据前移。

寻址公式

多维数组,一般先按行,再按列(或者先按列,再按行,这里以 先按行为例)的方式依次存储在连续的存储空间中。后续涉及多维数组时以二维数组为例

  • 一维数组:address_a[i] = base_address + i * data_type_size
  • 多维数组:假设二维数组:a[m][n] ,则 a[i][j] 的寻址公式:addres_a[i][j]=base_address + (i*n+j)*data_type_size

这些是数据结构中的特点,编程语言实际实现可能存在一些不同的地方。比如:

  • 编程语言中基础数组实际是不可变的,一旦创建不会再改变数组大小。
  • 不同的语言多维数组存储方式不一定都按照上面的寻址公式,可能每一行或者每一列连在一起,但行与行/列与列之间并不相连。

GO中的数组

声明与创建

声明需要指定数组的长度和数组中元素的类型,基础格式是 var arrRefVal [len]dataType,如声明一个长度为3的int类型数组 a :var a [3]int

在 GO 语言中,只有数组长度(即最大能存储的元素个数)和元素类型完全相同的才算做同一类型数组,两者缺一都会提示异常。

创建方式(下面示例将创建与声明合并):

// 基础写法
var  arrRefVal [len]dataType = [len]dataType{value0, value1, ..., valuek}
// 不指定长度,在编译期间通过源代码推导数组的大小,最终内部自动转换成上面的格式。
// 实质属于语法糖
var arrRefVal [...]dataType = {value0, value1, ..., valuek}
// 语法糖二,通过 `:=` 省去 `var` 关键字,等同于基础写法
arrRefVal :=[len]dataType{value0, value1, ..., valuek}
1
2
3
4
5
6
7

值复制

Go语言中的数组在赋值和函数调用中的形参都是值传递(Go中均是值传递)。意味着新形参的数组的变更,对源数组无效。

该规则对基础类型数与结构体数组均适用,简单示例:

// 声明并创建一个数组 a1
a1 :=[...]int{1,2,3,6,8}
// 声明一个数组 a2
var a2 [5]int
a2 = a1
// 声明并创建新数组a3
a3 := a1
// 修改a2的值
a2[1] = 5
// 查看三个数组的结果,可以看到:
// 三个数组地址不同
// 数组a2 的修改值后,其余两个不会跟着一起变
fmt.Println(">>>>>>>>>>>>>>WindCoder.com>>>>>>>>>>>>>>")
fmt.Printf("a1值:%v  ,a1地址:%p  , a1[0]地址:%p\n", a1,&a1,&a1[0])
fmt.Printf("a2值:%v  ,a2地址:%p  , a2[0]地址:%p\n", a2,&a2,&a2[0])
fmt.Printf("a3值:%v  ,a3地址:%p  , a3[0]地址:%p\n", a3,&a3,&a3[0]) 
fmt.Printf(">>>>>>>>>>>>>>WindCoder.com>>>>>>>>>>>>>>")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Go中存在指针:

  • & 用于获取指针地址,* 用于获取指针变量的值
  • Go语言不支持指针运算

内存存储

根据存储内容,大致可分为基础数据类型数组、结构体数组(即引用类型数组)、多维数组。

  • 基础数据类型数组中保存的是值
  • 引用类型数组中保存的是地址
  • 多维数组保存内容与一维数组的方式相同,先行后列依次存储

go_array.png

Java中的数组

声明与创建

声明的基础格式是 dataType[] arrRefVal 或者 dataType arrRelVal[],前者是常用格式。

如声明一个整型 int 的数组:int[] arry

声明数组,此时不存在初始化,仅在栈中存在变量名。

基础数组创建方式如下:


// 方案一  数组初始化为dataType的默认值
/**
 *   声明并初始化
 *   一、使用 dataType[arraySize] 创建了一个数组。
 *   二、把新创建的数组的引用赋值给变量 arrayRefVar。
 **/
dataType[] arrayRefVar = new dataType[arraySize];
arrayRefVar[i] = value0;

// 方案二
dataType[] arrayRefVar = new dataType[]{value0, value1, ..., valuek};

// 方案三 方案二的语法糖,编译器会自动编译成方案二的形式
dataType[] arrayRefVar = {value0, value1, ..., valuek};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

多维数组创建方式

//以二维基础数据类型数组为例,存在如下三种方式
int[ ][ ] arr = new int[3][4];
int[ ][ ] arr = new int[3][ ];
int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};
1
2
3
4

内存存储

Java 中数组根据存储内容,即dataType,可分为 基本数据类型数组、对象类型数组、多维数组

  • 基本数据类型数组:直接存储值
  • 对象类型数组:存储对象在内存中的地址
  • 多维数组:行内连续,行之间不一定连续

基本数据类型数组 int arr1 = {1,2,3,4}

  • arr1 在栈中
  • new 申请的空间在堆中,所以数组空间在堆中。
  • arr1 中保存的是数组空间的首地址
  • 数组空间中保存是基础数据类型

对象类型数组 User[] arr2 = {new User("ZhangSan"),new User("ZhaoSi"), new User("WangWu")}

  • 数组中保存的是对象的地址

多维数组:int[][] a3User[][] a4

  • 内存每一行是连续的,行与行之间不一定连续。
  • 内存中保存的内容和一维数组规则相同

go_java_array.png

预览
Loading comments...
0 条评论

暂无数据

example
预览