如何通过数组实现基本的集合功能(自动增长),本人是个java小白,近期学习有些收获,和大家分享一下

什么是集合

	集合的概念有些宽泛。这里讲的集合主要是可变长度的列表(也叫做动态数组)。
	下面这些都是集合:
  • 列表:一般是有序的集合,特点就是有顺序,比如链表、队列、栈等。

  • 集:一般是无序的集合,特点就是没有顺序并且数据不能重复,多数语言是使用散列表来实现的,支持对集进行添加、删除、查找包含等操作。

  • 多重集:一般是无序的集合,特点是没有顺序,但是数据可以有重复的值,支持对集进行添加、删除、查找包含、查找一个元素在集中的个数等操作。多重集一般可以通过排序转换为列表。

  • 关联数组:其实多数语言是使用散列表实现的,就是可以通过键(Key)获取到值(Value)。同样是没有顺序的。
    树、图:同样是集合。

集合的实现

这里以java中的ArrayList为例,它是一个数组的列表,其实就是数组的拓展,或者说是可变长度的数组。
ArrayList数组是基于数组实现的,这如何理解呢?其实就是在ArrayList里有个属性,这个属性是一个数组。另外,还会有个属性记录我们放了多少数据,这样我们再向其中放数据时,就会知道该向这个内部数组的哪个位置放数据了,但是这个数组也会有长度限制,若超过了这个限制该怎么办呢?当超过这个限制时,其内部会创建一个具有更长的长度的数组,然后把旧数组的数据复制到新数组里面,这样就可以继续往里面放数据了。

下面我们通过流程图来形象的理解一下这个流程吧

第一次写博客,图绘的挺丑的,大家看这个逻辑就好,原谅我这个手残党
下面我们先来简单地用代码实现这个变长数组。

package ArrayAndCollectionAndHashTable;

import java.util.Arrays;
//集合实现自动扩容
public class ArrayList {
	private static final int INITIAL_SIZE = 10;
	private int size = 0;
	private int[] array;
	
	public ArrayList() {
		//构造方法,声明了数组长度
		array = new int[INITIAL_SIZE];
	}
	
	public ArrayList(int initial) {
		//传入一个整型参数,判断这个参数是否合理(是否大于0),若大于0则以其为数组长度
		if(initial<=0) {
			initial = INITIAL_SIZE;
		}
		array = new int[initial];
	}
	
	/*添加元素*/
	public void add(int num) {
		//如果数组长度与size相等,那么利用copyOf方法将原先数组数值复制至新创建的数组内,并将新数组的引用地址赋给原引用
		if(size == array.length) {
			array = Arrays.copyOf(array,size*2);
		}
		array[size++] = num;//添加一条数据  size自增1
	}
	
	/*获取指定位置的元素值*/
	public int get(int i) {
		//如果指定下标大于等于数组长度,那么会抛出异常“获取的元素位置超过了最大长度”  否则会返回指定数据
		if(i>=size) {
			throw new IndexOutOfBoundsException("获取的元素位置超过了最大长度");
		}
		return array[i];
	}
	
	/*设置指定位置的元素值*/
	public int set(int i,int num) {
		//
		int oldNum = get(i);
		array[i] = num;
		return oldNum;
	}
	
	/*获取变长数组的长度*/
	public int size() {
		return size;
	}

}


这里以整型为例简单实现了变长数组。
可以看到其中有两个属性:一个是array,就是内部数组;另一个是size,用来存当前变长数组的长度。当调用add向变长数组中放值时,要确认内部数组是否足够放这个值,若不够,就生成一个长度是原数组长度的两倍的新数组,并且复制旧数组的数据到新数组里,再放值。
这里新建数组并复制旧数组的数据,是通过java内部的一个工具类实现的,底层调用的是本地方法(native),效率很高。

package ArrayAndCollectionAndHashTable;

public class ArrayListTest {
	public static void main(String[] args) {
		ArrayList arrayList = new ArrayList(1);//创建了一个数组长度为1的数组
		//向数组下标为0的位置添加数据1;size自增1,由0变为1
		arrayList.add(1);
		/*上一条记录里面size为1,与当前数组长度相等,则会创建一个新数组,数组长度为2倍的size,将老数组内容复制并赋给新数组,然后再进行添加操作,
		在数组下标为1的位置添加数据2;size自增为1,由1变为2*/
		arrayList.add(2);
		//数组当前长度为2,size为2,两者相等,将数组长度扩容至4;size自增1,变为3,数组存放第三个数据
		arrayList.add(3);
		//数组当前长度为4,size为3,存放第四个数据,size自增为4
		arrayList.add(4);
		//数组当前长度为4,size为4,两者相等,数组扩容至8,存放第五个数据,size自增为5
		arrayList.add(5);
		//获取arrayList数组下标为3的值并打印出来
		System.out.println(arrayList.get(3));
		//将arrayList数组下标为3的值替换为9
		arrayList.set(3,9);
		//获得arrayList下标为3的值并将其打印出来
		System.out.println(arrayList.get(3));
		//获得arrayList数组的长度(准确来说是数组存放最后一个元素+1的下标)并打印在控制台
		System.out.println(arrayList.size());
	}

}

上面的代码展示了如何调用变长数组来执行添加、修改、获取值、获取总长度操作。在调用过程中,我们完全不用在意其内部是怎么实现的,只需王里面添加值、获取值就好了。
ps:上面执行代码里面添加了很多的注释,这是我在学习的时候逻辑不太顺,添加注释方便自己理解,同学们可以不用在意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值