`
he_wen
  • 浏览: 239433 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java集合 之 动态数组

    博客分类:
  • Java
 
阅读更多

注意:首先本程序是根据javaeye博主:java_mzd,对里面的代码进行改进,改进的地方如下:

 

1、如何创建动态数组,并且为用户提供了动态扩展数组长度的接口

2、修改在数组指定位置添加元素

3、该数组适应于多线程环境

4、为该类添加删除一个元素的方法

 

 该类的优点:

                  1. 顺序表因为采用顺序存储形式,所以内部使用数组来存储数据
                  2.因为存储的具体对象类型不一定,所以采用泛型操作
                  3.数组操作优点:1.通过指针快速定位到下表,查询快速
 缺点:
                  1、当操作中超过容量时,则需要重新声明数组,并且复制当前所有数据

 

public class ArrayList<E> {
	private Object[] data = null;// 用来保存此队列中内容的数组
	private int current;// 保存当前为第几个元素的指标
	private int capacity;// 表示数组大小的指标
	/***
	 * 扩展数组的长度 ,也就是动态创建数组,默认扩展的长度为10
	 */
	private int extendLength;

	/**
	 * 如果初始化时,未声明大小,则默认为10
	 */
	public ArrayList() {
		this(10);
	}

	/**
	 * 初始化线性表,并且声明保存内容的数组大小
	 * @param initalSize
	 */
	public ArrayList(int initalSize) {
		if (initalSize < 0) {
			throw new RuntimeException("数组大小错误:" + initalSize);
		} else {
			this.data = new Object[initalSize];
			this.current = 0;
			capacity = initalSize;
			extendLength = 10;
		}
	}

	/**
	 * 添加元素的方法 添加前,先确认是否已经满了
	 * @param e
	 * @return
	 */
	synchronized public boolean add(E e) {
		ensureCapacity(current);// 确认容量
		this.data[current] = e;
		current++;
		return true;
	}

	/**
	 * 确认系统当前容量是否满足需要,如果满足,则不执行操作 如果不满足,增加容量
	 * @param cur 当前个数
	 */
	private void ensureCapacity(int cur) {
		if (cur == capacity) {
			// 如果达到容量极限,增加extendLength的容量,复制当前数组
			this.capacity = this.capacity + extendLength;
			Object[] newdata = new Object[capacity];
			System.arraycopy(this.data, 0, newdata, 0, this.capacity
					- extendLength);
			this.data = newdata;
		}
	}

	/**
	 * 得到指定下标的数据
	 * @param index
	 * @return
	 */
	public E get(int index) {
		validateIndex(index);
		return (E) this.data[index];
	}

	/**
	 * 返回当前队列大小
	 * @return
	 */
	public int size() {
		return this.current;
	}

	/**
	 * 更改指定下标元素的数据为e
	 * @param index 
	 * @param e
	 * @return
	 */
	public boolean set(int index, E e) {
		validateIndex(index);
		synchronized(data){
			this.data[index] = e;
		}
		return true;
	}

	/**
	 *  验证当前下标是否合法,如果不合法,抛出运行时异常
	 * @param index 下标
	 */
	private void validateIndex(int index) {
		if (index < 0 || index > current) {
			throw new RuntimeException("数组index错误:" + index);
		}
	}

	/**
	 * 在指定下标位置处插入数据e
	 * @param index 指定数组的位置,从 0 开始
	 * @param e 需要插入的数据
	 * @return 
	 */
	synchronized public boolean insert(int index, E e) {
		validateIndex(index);
		ensureCapacity(current);
		Object[] tem = new Object[current+1];// 用一个临时数组作为备份
		//开始备份数组
//		for (int i = 0; i < current; i++) {
//			if (i < index) {
//				tem[i] = this.data[i];
//			} else if (i == index) {
//				tem[i] = e;
//			} else if (i > index) {
//				tem[i] = this.data[i - 1];
//			}
//		}
		if(index<=0){
			System.arraycopy(data,0,tem,1 , current);
			tem[index]=e;
		}else if(index<=current-1){
			System.arraycopy(data,0,tem,0,index);
			tem[index]=e;
			System.arraycopy(data,index, tem, index+1,current-index);
		}else{
			System.arraycopy(data,0,tem,0,current);
			tem[index]=e;
		}
		current++;
		this.data = tem;
		return true;
	}
	/****
	 * 从数组中删除一个元素
	 * @param e 要删除的元素
	 * @return 如果待删除的元素在数组中没有找到,就返回false,否则返回true
	 */
	public boolean FromArrayDelete(E e) {
		synchronized (data) {
			int n = -1;
			for (int i = 0; i < current; i++) {//在数组中寻找待删除的元素
				if (data[i] == e) {
					n = i;
					break;
				}
			}
			if (n < 0)//如果在数组中没有找到返回false
				return false;
			Object temp[] = new Object[current - 1];
			int j = 0;
			for (int i = 0; i < current; i++) {
				if (i != n)//j++的原因就是,过滤掉删除元素的那个位置
					temp[j++] = data[i];
			}
			current--;
			capacity--;
			data = temp;
			return true;
		}
	}

	public int getExtendLength() {
		return extendLength;
	}

	/***
	 * 可以设置一次性扩展数组的长度
	 * @param extendLength 设置的长度
	 */
	synchronized public void setExtendLength(int extendLength) {
		this.extendLength = extendLength;
	}

	public int getCurrent() {
		return current;
	}

}
 
分享到:
评论
9 楼 walter_hu 2010-12-12  
原来是思路有些不同 呵呵~
8 楼 walter_hu 2010-12-12  
LZ的数组的扩容时机,我感觉有些不理解...
7 楼 只想做麻雀 2010-12-10  
goolcona 写道

还有一个问题,不知道Object[E]的这个E是否允许重新被指向其他对象:
Object[] data,get方法返回的是 E ,如果E是数组或者集合之类的对象,可以在外部 E e = get() 后, e = anotherE(); 这时因为不是基本数据类型,private Object[index] 指向的e这个对象也被更改了;
如果本身就只是一个存放对象的话那么是没有问题的。

所以说lz讲下这个类的应用场景最好。


恕我愚昧啊,在外部 E e = get() 后, e = anotherE();,怎么会影响到Object[index] 指向的e这个对象!?

如果我改动这个对象当然会影响到,改变e的引用和Object[index]指向的无关啊。
6 楼 he_wen 2010-12-09  
谢谢你,我已经明白了,需要同一个锁保证同步的数据类存可见,我这样用确实危险。。。
5 楼 jbon 2010-12-09  
好好看看同步吧
4 楼 he_wen 2010-12-09  
请问你一下这两个方法没有必然的联系,那么就不能用两个不同的锁吗?还是不明白,能不能举个例子,谢谢。。。

多虑了,肯定是只能存放一种类型了了,谢谢你的想法。。。
3 楼 goolcona 2010-12-09  
锁的持有者是对象,synchronized public void setExtendLength()加锁的对象是类产生的对象,针对这个类就是 ArrayList a = new ArrayList() a这个对象;
synchronized (data) 这个锁的对象是data,两个锁的对象不同;

还有一个问题,不知道Object[E]的这个E是否允许重新被指向其他对象:
Object[] data,get方法返回的是 E ,如果E是数组或者集合之类的对象,可以在外部 E e = get() 后, e = anotherE(); 这时因为不是基本数据类型,private Object[index] 指向的e这个对象也被更改了;
如果本身就只是一个存放对象的话那么是没有问题的。

所以说lz讲下这个类的应用场景最好。
2 楼 he_wen 2010-12-09  
public boolean FromArrayDelete(E e) {  synchronized (data) {,
请问一下问题在哪里,可以让我好好改正谢谢。。。
1 楼 goolcona 2010-12-09  
1)lz写下这个类的应用场景吧,没想出比java.util.ArrayList好在哪里;
2)public boolean FromArrayDelete(E e) {  synchronized (data) {
这个锁是有问题的。

相关推荐

    Java 集合与数组

    集合在程序设计中是一种重要的数据结构,Java 提供了有关集合的类库,我们称之为 Collection API,其接口和类主要位于 java.util 包中。 Collection API Collection API 是 Java 提供的集合类库,主要包括了集合...

    java 动态数组的体现

    本篇文章将深入探讨Java中的动态数组实现,主要关注ArrayList类,它是Java集合框架中的一种重要实现,体现了动态数组的概念。 首先,我们来看看ArrayList的内部机制。ArrayList是基于数组实现的,它继承自...

    accp5.0java第八章 数组(改)

    9. **Java集合框架与数组的关系**:虽然数组是基础,但Java集合框架提供了更灵活的数据结构,如ArrayList和LinkedList,它们在某些场景下比数组更具优势。 10. **性能考虑**:数组在内存分配上是静态的,一旦创建,...

    数组和集合

    在编程领域,尤其是Java语言中,数组和集合是处理数据的两种基本方式。数组(Array)是同类型数据的有序集合,而集合(Collection)则是更加灵活的数据结构,可以存储任意类型的对象。Java为这两种数据存储方式提供...

    java 动态的数组链表

    动态数组链表,也称为ArrayList,是Java集合框架中的一种实现,位于`java.util`包下。ArrayList类继承自AbstractList,并实现了List接口,提供了一种动态增长的数组。当数组达到其容量限制时,ArrayList会自动创建一...

    java实验数组和集合

    Java 实验数组和集合 Java 是一种广泛使用的编程语言,数组和集合是 Java 语言中的两个基本数据结构。数组是一种固定大小的同类型元素的集合,而集合是一种可以动态增长和缩减的元素集合。在 Java 中,数组和集合都...

    Java第5章 数组 含源代码

    Java集合框架中的`Arrays`类提供了对数组排序的方法,如`Arrays.sort()`,可用于整型、字符型等基本类型的数组,也可通过自定义比较器对对象数组进行排序。 八、数组与集合框架的关系 虽然数组是Java的基础,但集合...

    两个数组之间新增集合,公共集合,减少的集合

    这只是一个简单的工具类java中处理两个数组之间元素的情况,具体的情况可以分为:两个数组之间新增集合,公共集合,减少的集合

    Java程序设计 3 数组与集合 简图.ppt

    实现集合可以通过实现Collection接口来完成,Collection接口是Java集合框架中的一个接口,Collection接口的实现类有ArrayList、LinkedList等。Collection接口的常用方法有add、remove、contains等。 小结 本节课...

    Java取得两个数组中不同的元素

    该源代码很好地体现了数组与List之间的转换,同时也体现了两个集合的合并操作

    java程序控制与数组 详解 java实例20

    接下来是数组,它是Java中的一个重要数据结构,用于存储同一类型的数据集合。数组在内存中分配一块连续的空间,每个元素可以通过索引来访问。Java支持一维、二维和多维数组。例如,一维数组可以看作是一条线性的列表...

    Educoder题目:Java入门 - 数组进阶答案解析.md

    Educoder题目:Java入门 - 数组进阶答案解析

    java中两个byte数组实现合并的示例

    这是通过创建一个新的足够大的字节数组`data3`来实现的,其长度等于`data1`和`data2`的长度之和,然后利用`System.arraycopy()`方法将`data1`和`data2`的内容复制到新数组中。 ```java public static byte[] ...

    java 数组的合并

    Java的ArrayList类提供了便利的数组操作,包括动态扩容和数组合并。我们可以在ArrayList中添加数组元素,然后使用toArray()方法转换回数组。 ```java int[] array1 = {1, 2, 3}; int[] array2 = {4, 5, 6}; ...

    java从n个数组中取出所有的组合

    在Java编程中,"从n个数组中取出所有的组合"是一个经典的算法问题,涉及到排列组合的概念。这通常可以通过回溯法或递归策略来解决。下面我们将深入探讨这个主题。 首先,我们需要理解“排列”与“组合”的概念。...

    5-Java数组与方法

    首先,数组是Java中的基本类型之一,它是由相同类型的数据项组成的有序集合。每个数据项都有一个唯一的索引,从0开始,到数组长度减1。例如,一个整型数组int[] numbers可以存储一系列的整数,如numbers[0], numbers...

    Java基础教程:数组和集合

    Java 基础教程:数组和集合 Java 中的数组和集合是两个非常重要的概念,它们用于存储和操作数据。在本文中,我们将详细介绍 Java 中的数组和集合,包括它们的定义、初始化、访问和常见操作。 数组(Array) 数组...

    Java对象、数组、集合转换为Json(Json转化为Java对象、数组、集合)

    这是本人写的一个基于JSON的完整项目,实现了Java对象、数组、集合转换为Json(Json转化为Java对象、数组、集合)。这是一个完整的项目,下载解压后直接导入MyEclipse/Eclipse中,运行com.demo.JSONDemo类即可看到效果...

    java中如何将数组转为list集合

    java 数组转list+java中如何将数组转为list集合

    java-对象数组转换为json

    在IT领域,特别是Java编程中,对象数组与JSON之间的转换是一项常见且重要的操作。下面将深入探讨如何在Java中实现对象数组向JSON的转换,并反过来将JSON字符串转换为Java对象数组,同时也会提及一些相关技术和代码...

Global site tag (gtag.js) - Google Analytics