java 实体类arraylist_如何实现Java的ArrayList经典实体类
arraylist是java集合框架中一个经典的实现类。他比起常用的数组而言,明显的优点在于,可以随意的添加和删除元素而不需考虑数组的大小。处于练手的目的,实现一个简单的arraylist,并且把实现的过程在此记录。
实现的arraylist主要的功能如下:
默认构造器和一个参数的有参构造器
add方法
get方法
indexof方法
contains方法
size方法
isempty方法
remove方法
sort方法
这个简单的arraylist类 取名为simplearraylist,全部的代码查看simplearraylist代码
构造器
源码arraylist一共有三个构造器,一个无参构造器,一个参数为int型有参构造器,一个参数为collection型的有参构造器。参数为collection型的构造器用来实现将其他继承collection类的容器类转换成arraylist。simplearraylist类因为还没有手动实现其他的容器类,所以实现的构造方法只有2个。代码如下:
public simplearraylist(){
this(default_capacity);
}
public simplearraylist(int size){
if (size < 0){
throw new illegalargumentexception("默认的大小" + size);
}else{
elementdata = new object[size];
}
}
无参构造器中的 default_capacity是定义的私有变量,默认值是10,用来创建一个大小为10的数组。有参构造器中,int参数是用来生成一个指定大小的object数组。将创建好的数组传给elementdata。elementdata是真正的用来存储元素的数组。
add方法
add 方法用来往容器中添加元素,add方法有两个重载方法,一个是add(e e),另一个是add(int index, e e)。add本身很简单,但是要处理动态数组,即数组大小不满足的时候,扩大数组的内存。具体的代码如下:
public void add(e e){
iscapacityenough(size + 1);
elementdata[size++] = e;
}
方法iscapacityenough就是来判断是否需要扩容,传入的参数就是最小的扩容空间。因为add一个元素,所以最小的扩容空间,即新的长度是所有元素+ 1。这里的size就是真正的元素个数。
private void iscapacityenough(int size){
if (size > default_capacity){
explicitcapacity(size);
}
if (size < 0){
throw new outofmemoryerror();
}
}
判断扩容的方法也很简单,判断需要扩容的空间是不是比默认的空间大。如果需要的空间比默认的空间大,就调用explicitcapacity进行扩容。这里有个size小于0的判断,出现size小于0主要是因为当size超过integer.max_value就会变成负数。
private final static int max_array_length = integer.max_value - 8;
private void explicitcapacity(int capacity){
int newlength = elementdata.length * 2;
if (newlength - capacity < 0){
newlength = capacity;
}
if (newlength > (max_array_length)){
newlength = (capacity > max_array_length ? integer.max_value : max_array_length);
}
elementdata = arrays.copyof(elementdata, newlength);
}
上面的代码是扩容的代码,首先,定义一个数组最大的容量的常量为最大值,这个值按照官方的源码中的解释是要有些vm保留了数组的头部信息在数组中,因此实际存放数据的大小就是整数的最大值 - 8
然后设定一个要扩容的数组的大小,虽然上面说了有一个扩容空间的值 size + 1 ,这个是实际我们最小需要扩容的大小。但为了继续增加元素,而不频繁的扩容,因此一次性的申请多一些的扩容空间。这里newlength 打算申请为 数组长度的2倍,然后去判断这个长度是否满足需要的扩容空间的值。 即有了后续的两段代码
if (newlength - capacity < 0){
newlength = capacity;
}
if (newlength > (max_array_length)){
newlength = (capacity > max_array_length ? integer.max_value : max_array_length);
}
如果2倍的长度仍然不满足,则申请到需要的扩容长度。在我们只增加一个元素的情况下,这个判断是永远不会生效的,但是如果有addall方法,则增加的元素很多,就要导致一次申请2倍的长度是不够的。第二个判断是判断newlength的长度如果超过上面定义的数组最大长度则判断要需要的扩容空间是否大于数组最大长度,如果大于则newlength为 max_value ,否则为 max_array_length。
最后,真正实现数组扩容到设定长度的方法就没意思了,调用arrays.copyof(elementdata, newlength)得到一个扩容后的数组。
add的另一个重载方法也很简单。
public void add(int index, e e) {
//判断是不是越界
checkrangeforadd(index);
//判断需不需要扩容
iscapacityenough(size + 1);
//将index的元素及以后的元素向后移一位
system.arraycopy(elementdata,index,elementdata,index + 1,size - index);
//将index下标的值设为e
elementdata[index] = e;
size++;
}
private void checkrangeforadd(int index){
//这里index = size是被允许的,即支持头,中间,尾部插入
if (index < 0 || index > size){
throw new indexoutofboundsexception("指定的index超过界限");
}
}
至此,一个简单的add方法就实现完了。
get方法
get方法用来得到容器中指定下标的元素。方法实现比较简单,直接返回数组中指定下标的元素即可。
private void checkrange(int index) {
if (index >= size || index < 0){
throw new indexoutofboundsexception("指定的index超过界限");
}
}
public e get(int index){
checkrange(index);
return (e)elementdata[index];
}
indexof方法
indexof方法用来得到指定元素的下标。实现起来比较简单,需要判断传入的元素,代码如下:
public int indexof(object o){
if (o != null) {
for (int i = 0 ; i < size ; i++){
if (elementdata[i].equals(0)){
return i;
}
}
}else {
for (int i = 0 ; i < size ; i++){
if (elementdata[i] == null) {
return i;
}
}
}
return -1;
}
判断传入的元素是否为null,如果为null,则依次与null。如果不为空,则用equals依次比较。匹配成功就返回下标,匹配失败就返回-1。
contains方法
contains用来判断该容器中是否包含指定的元素。在有了indexof方法的基础上,contains的实现就很简单了。
public boolean contains(object o){
return indexof(o) >= 0;
}
size方法
size方法用来得到容器类的元素个数,实现很简单,直接返回size的大小即可。
public int size(){
return size;
}
isempty方法
isempty方法用来判断容器是否为空,判断size方法的返回值是否为0即可。
public boolean isempty(){
return size() == 0;
}
remove方法
remove方法是用来对容器类的元素进行删除,与add一样,remove方法也有两个重载方法,分别是
remove(object o)和remove(int index)
public e remove(int index) {
e value = get(index);
int movesize = size - index - 1;
if (movesize > 0){
system.arraycopy(elementdata,index + 1, elementdata,index,size - index - 1);
}
elementdata[--size] = null;
return value;
}
public boolean remove(object o){
if (contains(o)){
remove(indexof(o));
return true;
}else {
return false;
}
}
第一个remove方法是核心方法,首先得到要删除的下标元素的值,然后判断index后面的要前移的元素的个数,如果个数大于零,则调用库方法,将index后面的元素向前移一位。最后elementdata[--size] = null;缩减size大小,并将原最后一位置空。
第二个remove方法不需要向第一个方法一样,需要告诉使用者要删除的下标对应的元素,只需要判断是否删除成功即可。如果要删除的元素在列表中,则删除成功,如果不在则失败。因此调用contains方法就可以判断是否要删除的元素在列表中。在则调用remove(int index),不在则返回失败。
总结
自此,一个简单的arraylist就实现完了,实现的目的是为了弄清arraylist动态数组的原理以及add与remove方法的内容实现。同时,也清楚了arraylist最大的扩容空间就是integer的最大值。该类的所有代码在simplearraylist代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持萬仟网!
希望与广大网友互动??
点此进行留言吧!
java 实体类arraylist_如何实现Java的ArrayList经典实体类相关推荐
- java实体类实现抽象类_java接口、抽象类、实体类关系介绍
接口:接口是一个引用类型,与类相似,不过在接口中只能包含常量,方法名和嵌套类型.没有构造器,所以不能被实例化只能被类所实现或者被另外的接口所继承.在接口中声明的方法没有方法体. 抽象类:将类层次中共有 ...
- Hibernate实体映射配置1(java@注解方式)
实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取.在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义. 本文以java注解的形式总结映射关 ...
- Java程序设计语言基础05:Java的类和对象
目录 1. 类的定义与组成 1.1 类的定义 2.2 类的使用 2. 类.对象和引用 2.1 类 2.2 对象 2.3 引用 3. 类的知识扩展 3.1 成员变量初始值 3.2 在类中定义自己的引用 ...
- java函数修饰符_Java 函数 面向对象,修饰符,类,构造方法,this
1.函数 函数就是定义在类中,具有特定功能的一段小程序. 在面向对象编程的语言中,函数也叫方法. 2.函数的格式 修饰符 返回值类型 函数名(参数类型 实际参数,....) { 执行语句; retur ...
- 类和对象(Java)
类和对象(Java) 类定义和使用 类的实例化 类的成员 this 指针 访问限定符 static 内部类 类和对象的内存布局 Java是一门纯面向对象的的语言,在面向对象的世界里,一切皆为对象.面向 ...
- 二、java项目常用工具类之beancopy,bean和map转换工具类
项目环境: jdk1.8+spring4.3.12 一.问题描述及试用场景: 在项目规范中,要求类名以DO为尾的类作为数据库层实体bean,类名以MO为尾的类作为系统传输层实体bean,类名以VO为尾 ...
- 哪些类用来实现java反射机制_JAVA反射机制
运行时类型识别(Run-time Type Identification, RTTI)主要有两种方式,一种是我们在编译时和运行时已经知道了所有的类型,另外一种是功能强大的"反射"机 ...
- Java 编程问题:七、Java 反射类、接口、构造器、方法和字段
原文:Java Coding Problems 协议:CC BY-NC-SA 4.0 贡献者:飞龙 本文来自[ApacheCN Java 译文集],自豪地采用谷歌翻译. 本章包括涉及 Java 反射 ...
- java 分析类_java--分析简单java类与反射的联系
分析简单java类与反射的联系 web对反射的操作支持 在JSP之中有一种技术--javaBean.而且在jsp里面也配套有相应的操作方式,javaBean的核心在于简单java类,于是下面演示此操作 ...
最新文章
- MimbleWimble 系列之Pedersen 承诺
- c的按位取反运算符(~) 与逻辑逻辑(!)
- 谷歌又有手机黑科技:进入办公室就变静音,遇车祸自动报警
- adb通信协议分析以及实现(二):adb服务进程发现设备
- 记一次项目中由id类型引起的bug
- 小程序访问本地服务器拒绝访问,文件夹拒绝访问的原因与解决办法
- eclipse 面包屑开关 / 查看class再哪个jar中
- winfrom软件开发汽车测试_ETci — 全自动软件测试调度(持续集成)平台
- 偏函数 匿名函数 高阶函数 map filter reduce
- win32_bios 的对象编辑器无法保存对象_怎样创建Femap对象
- IMP-00009: 导出文件异常结束 imp
- Oracle 行列转换2
- 从无线安全到内网渗透(转)
- Android SoundPool循环播放
- winrar解压器_与WinRAR齐名的经典解压缩软件——WinZip,不仅仅是情怀
- 玩转web表单网页快速开发(❤建议收藏❤)
- linux多网卡的路由模式和桥接模式设置方法
- 中国石油大学《计算机网络课程设计》第三次在线作业
- java.lang.NoClassDefFoundError:无法初始化类org.hibernate.validator.internal.engine.ConfigurationImpl
- 我也玩android了
热门文章
- improve php,解析提高PHP执行效率
- 台湾大学林轩田机器学习基石课程学习笔记3 -- Types of Learning
- tf.nn.conv2d() / tf.nn.depthwise_conv2d() 和 Batchsize效益
- 3DSlicer22:Module-ExtensionWizard Build Install
- Google服务器 IP
- C 语言的基本数据类型
- BIOS功能调用之滚屏与清屏
- 【 ➰斗艳争妍の网络协议姐妹花️➰】http协议 VS websocket协议
- MyBatis-Plus 高级功能 —— 实现逻辑删除
- IntelliJ Idea解决Could not autowire. No beans of 'xxxx' type found的错误提示