`
商山居士
  • 浏览: 9060 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

动态数组与泛型

 
阅读更多

      学习编程语言的人都知道数组是具有相同数据类型的一组数据集合,java中将数组看做一个对象,虽然基本的数据类型不是对象,但是由基本的数据类型组成的数组则是对象,所以在程序设计中引入数组可以有效的管理和处理数据,数组则有静态数组和动态数组之分;静态数组有时候存在自身的不足,比如一个会场现有30个人,所以摆了30把椅子,但是后续有人再来,这三十把椅子肯定不够,再比如,实际来了30个人,你摆了300把椅子,这不就构成资源浪费吗?在实际生活中根据参加会议人数情况可以适当增加或减少椅子,同样在java中也可以引入动态数组解决编程问题;下面看一个动态数组的例子

/**
 * 动态数组,用来装字符串的动态数组
 * 
 * @author 王伟
 * 
 */
public class ArrayQueue {
	
	//定义一个用来存放数据的数组
	//初始长度为0,表示没有装任何数据
	String[] src = new String[0];
	

	/**
	 * 将指定的元素加入容器
	 * 
	 * @param s
	 *            要加入到容器中的元素
	 */
	public void add(String s) {
		//定义一个新数组,用来装数据,长度比src+1
		String[] dest = new String[src.length+1];
		//将新加进的元素放入新数组的最后一个下标位置
		dest[dest.length-1]=s;
		//将原来数组中的数据按照下标顺序拷贝到新数组
		for(int i=0;i<src.length;i++){
			dest[i] = src[i];
		}
		
		//将src指向新数组
		src = dest;

	}

	/**
	 * 获取指定下标位置的元素
	 * 
	 * @param index
	 *            要获取的元素的下标
	 * @return 返回获取到的元素
	 */
	public String get(int index) {
		return src[index];
	}

	/**
	 * 修改指定位置元素的值
	 * 
	 * @param index要修改的元素位置
	 * @param s
	 *            修改后的新元素
	 */
	public void update(int index, String s) {

	}
	
	
	/**
	 * 将指定元素插入到指定位置
	 * @param index 要插入元素的位置
	 * @param s 要插入的新元素
	 */
	public void insert(int index, String s) {

	}
	

	/**
	 * 删除指定位置的元素
	 * 
	 * @param index
	 *            要删除的元素的下标
	 */
	public void delete(int index) {

	}

	/**
	 * 获得容器中元素个数的方法
	 * 
	 * @return 返回元素的个数
	 */
	public int size() {
		return src.length;
	}

}

 通过以上例子可以看出动态数组的好处在于其长度可以改变,适当的解决了静态数组遗留的一些问题,java中Object是最上层的父类,在程序设计时通常传入的值与返回的值都以Object类型为主;如果在类名后添加一个<E >语句,则使用了泛型机制,是动态数组可以装任意类型的数据;比如一块地我们为它分配10颗桃树作为实验,以后逐年增加10颗,下面看一个使用泛型动态数组的例子

/**
 * 动态数组,用来装任意类型的动态数组
 * 
 * @author 王伟
 * 
 */
public class ArrayQueue<E> {

	private int len = 0;// 长度
	private int  Capacity;// 初始容量
	private int rate;// 增长比率
	// 定义一个用来存放数据的数组
	// 初始长度为0,表示没有装任何数据
	Object[] src;

	public ArrayQueue() {
		this.initContiner = 10;
		this.rate = 10;
		src = new Object[initContiner];
	}

	// 创建容器对象的时候指定容量和增长比率
	public ArrayQueue(int initContiner, int rate) {
		this.initContiner = initContiner;
		this.rate = rate;
		src = new Object[initContiner];
	}

	/**
	 * 将指定的元素加入容器
	 * 
	 * @param s
	 *            要加入到容器中的元素
	 */
	public void add(E s) {
		// 如果长度小于容量,就将元素放到数组第一个为null的位置
		if (len >= src.length) {
			// 创建新数组
			// 定义一个新数组,用来装数据,长度比src+1
			Object[] dest = new Object[src.length + rate];
			// 将源数组中的数据按照下标顺序拷贝到新数组
			System.arraycopy(src, 0, dest, 0, len);
			src = dest;

		}
		src[len] = s;

		len++;
	}

	/**
	 * 获取指定下标位置的元素
	 * 
	 * @param index
	 *            要获取的元素的下标
	 * @return 返回获取到的元素
	 */
	public E get(int index) {
		return (E) src[index];
	}

	/**
	 * 修改指定位置元素的值
	 * 
	 * @param index要修改的元素位置
	 * @param s
	 *            修改后的新元素
	 */
	public void update(int index, E s) {
		if (index >= 0 && index < size()) {
			src[index] = s;
		} else {
			System.out.println("指定的下标超出范围!!!");
		}

	}

	/**
	 * 将指定元素插入到指定位置
	 * 
	 * @param index
	 *            要插入元素的位置
	 * @param s
	 *            要插入的新元素
	 */
	public void insert(int index, E s) {
		if (index >= 0 && index < size()) {
			// 定义新数组,长度比原数组+1
			Object[] dest = new Object[src.length + 1];
			// 将新元素放到新数组的指定位置
			dest[index] = s;
			// 将源数组中下标<index,拷贝到新数组相同的下标位置
			for (int i = 0; i < index; i++) {
				dest[i] = src[i];
			}

			// 将源数组中其他下标的元素拷贝到新数组下标+1的位置
			for (int i = index; i < src.length; i++) {
				dest[i + 1] = src[i];
			}
			// 将src指向新数组
			src = dest;

		} else {
			System.out.println("指定的下标超出范围!!!");
		}
	}

	/**
	 * 删除指定位置的元素
	 * 
	 * @param index
	 *            要删除的元素的下标
	 */
	public void delete(int index) {
		if (index >= 0 && index < size()) {
			// 定义新数组,长度是原始数组长度-1
			Object[] dest = new Object[src.length - 1];

			// 如果下标<index,则按下标位置拷贝
			for (int i = 0; i < index; i++) {
				dest[i] = src[i];
			}
			// index位置的值丢掉不需要拷贝

			// >index的下标位置拷贝到新数组下标-1的位置
			for (int i = index + 1; i < src.length; i++) {
				dest[i - 1] = src[i];
			}
			// 将src指向新数组
			src = dest;

		} else {
			System.out.println("指定的下标超出范围!!!");
		}
	}

	/**
	 * 获得容器中元素个数的方法 容器中不为null的元素个数
	 * 
	 * @return 返回元素的个数
	 */
	public int size() {
		return len;
	}
}

 这样就很好的解决了,分配大了浪费空间,小了容量不够,还有某些for循环的效率不高等问题,泛型的优点和好处在于使用泛型定义类在声明该类对象时可以根据不同的需求指定<E>真正的类型,而在使用类中的方法传递或返回数据类型时候将不在需要进行类型转换操作而是使用在声明泛型对象时<E>中设置的类型,通过下面例子来加深理解

//定义泛型类

public class OverClass <E>{
	//定义泛型成员变量
	private E over;
	//设置getxxx()方法
	public E getOver(){
		return over;
	}
	//设置setxxx()方法
	public void setOver(E over){
		
		
	}
	public static void main(String[] args){
		//实例化一个Boolean型对象
		OverClass<Boolean> over = new OverClass<Boolean>();
		//实例化一个Float对象
		OverClass<Float> over1 = new OverClass<Float>();
		//不需要进行类型转换
		over.setOver(true);
		over1.setOver(12.3f);
		//不需要进行类型转换
		Boolean b =over.getOver();
		Float f = over1.getOver();
		System.out.print(b);
		System.out.print(f);
		
		
		
	}
	
	

}

 其实以上例子还可已不用泛型也能写出,但是经常在调用方法时候会出现“向上转型”和“向下转型”的问题;大家都知道在java中向上转型是安全的向下转型会出问题有可能出现异常,所以泛型就很好的解决了这一问题,在这里就不举例说明了,泛型的常规用法读者可以参考API文档自己摸索,这里不多做解释,在下一篇说明集合类以后,会将集合和泛型综合说明,

分享到:
评论

相关推荐

    数组,泛型,字典表,哈希表的用法

    在编程领域,数组、泛型、字典表(又称哈希表)是数据结构与算法中的基础概念,它们在存储和操作数据时起着至关重要的作用。以下是关于这些概念的详细说明: 1. **数组**:数组是一种线性数据结构,它包含固定数量...

    泛型动态数组

    泛型动态数组泛型动态数组

    Delphi泛型动态数组的扩展.3.rar

    尽管这些文件不直接涉及泛型动态数组,但它们展示了如何将泛型与底层系统交互,比如在分析不同架构下的指令时,泛型可能用于创建适应多种处理器类型的代码。 至于".bat"文件,"clean.bat"可能是一个清理脚本,用于...

    C#【泛型】实现的【通用】结构体转字节数组

    C#【泛型】实现的【通用】结构体转字节数组,包含网上收集的网页参考资料、非通用的【StructTest】工程、泛型实现的通用【Struct2BytesGenericType】工程。 VS2010编译运行。

    java数组、泛型、集合在多态中的使用及对比

    与泛型不同,`List&lt;Object&gt;`是一个父接口,它可以引用任何类型的集合,包括`ArrayList&lt;Animal&gt;`或`ArrayList&lt;Dog&gt;`。因此,它在多态中的使用更加灵活,可以处理各种类型的集合。然而,这种灵活性也意味着安全性较低...

    动态数组末班类源代码

    7. 性能考虑:虽然这个动态数组类为初学者提供了学习基础,但与标准库中的`std::vector`相比,可能存在性能上的差异。`std::vector`经过优化,可能提供更好的内存对齐和更高效的内存管理。 8. 编程实践:通过学习和...

    实例185 - 自定义泛型化数组类

    这样的设计确保了类型安全,因为我们只能向数组中添加与泛型类型一致的元素。 然而,需要注意的是,由于Java的类型擦除,上述代码中的`array = (T[]) new Object[size];`实际上是一个潜在的类型转换异常风险。在...

    泛型顺序队列和循环队列

    这种队列在处理大量数据流时有更高的效率,因为它避免了数组的动态扩展和收缩。在C#中,我们可以通过自定义类来实现泛型循环队列,通常需要维护两个指针,一个指向队首,一个指向队尾,同时管理数组的边界条件。 在...

    数据结构中的动态数组模版类

    动态数组确保了内存管理的灵活性,而模版则提供了泛型编程的能力,使该类可以应用于任何满足基本操作的数据类型。 在压缩包文件“CArray动态数组”中,很可能包含了实现上述功能的C++源代码文件。这些文件可能包括...

    Java 泛型总结(二):泛型与数组

    Java 泛型总结(二):泛型与数组 Java 中泛型数组的关系确实有些复杂,不允许直接创建泛型数组,本文将分析其中的原因,并总结一些创建泛型数组的方式。 首先,让我们看看数组和泛型的关系。数组相比于 Java ...

    泛型自定义数组大小

    3. **泛型类与数组**: 自定义泛型类可以模拟数组的行为,但比数组更灵活。我们可以通过泛型类定义一个可以容纳任意类型对象的容器,同时规定容器中元素的类型。这样可以确保添加到容器中的元素都是同类型的,从而...

    CNewArr C++写的动态数组类

    动态数组与静态数组的主要区别在于,静态数组在编译时就必须确定大小,而动态数组则可以在程序运行时根据需求进行调整。 1. **数据类型模板**: CNewArr类通常会使用模板来实现对多种数据类型的兼容性。模板是一种...

    C++动态数组模板实现

    通过以上步骤,我们可以创建一个功能完备且泛型化的动态数组类。这个类可以像标准库中的`std::vector`那样使用,支持各种操作,并且对任何数据类型都有效。模板的使用使得代码更具通用性,提高了代码的可重用性和...

    jsp编程中,servlet向jsp中传递带有泛型的数组

    servlet类向jsp传递带泛型数组。泛型为自定义的bean

    动态数组链表数据结构.docx

    动态数组链表数据结构 动态数组链表数据结构是一种特殊的数据结构,它将动态数组和链表的优点结合起来,形成了一种高效、灵活的数据存储方式。下面我们将详细介绍动态数组链表数据结构的组成、特点、优缺点和应用...

    C#中动态声明与使用对象数组实例

    在C#编程语言中,动态声明与使用对象数组是一种常见的操作,特别是在处理不确定数量的数据时。本实例将探讨如何在C#中实现这一功能,并关注数组的声明、使用、数据保护以及内存管理。 首先,我们要了解C#中的数组。...

    泛型集合与数组应用老师找学生

    泛型集合提供了更多的灵活性,可以动态地添加、删除元素,适合于数据量变化的情况。而数组则在访问速度上稍占优势,特别适用于需要快速访问特定位置数据的情况。在“老师找学生”这个场景下,如果需要频繁地添加或...

    Delphi泛型动态数组的扩展.1.mht

    Delphi泛型动态数组的扩展.1.mht

    Delphi泛型动态数组的扩展.2.mht

    Delphi泛型动态数组的扩展.2.mht

    java反射全解(反射原理+反射API详解+反射与数组+反射与泛型+反射源码与性能开销+反射优缺点+反射与内省)

    反射机制的分类包括反射 API、反射与数组、反射与泛型、反射源码与性能开销、反射优缺点、反射与内省等。 反射 API 是 Java 语言提供的一组 Application Programming Interface(API),用于在运行时获取类的信息和...

Global site tag (gtag.js) - Google Analytics