Java数据结构:ArrayList与顺序表2

前一篇文章中,我们学习了如何模拟实现ArrayList类中的增删查改方法等,以及在使用ArrayList数组时必须实例化对象,因为ArrayList类是一个泛型类,需要明确传递的参数类型。

现在接着学习ArrayList类中的细节。

四、ArrayList的使用

看看ArrayList的源码中的一些成员变量:

ArrayList的构造方法

|----------------------------------------|------------------------------|
| 方法 | 解释 |
| ArrayList() | 无参构造 |
| ArrayList(int initialCapacity) | 指定顺序表初始容量 |
| ArrayList(Collection<? extends E> c) | 利用其他 Collection 构建 ArrayList |

带参数的构造方法

1.ArrayList(int initialCapacity)

观看这个构造方法的源码:这个构造方法初始化了顺序表的容量

示例:构造一个具有10个容量的顺序表

在容量范围内,可以往数组中新增元素,但是ArrayList泛型类中已经规定了可以传递的参数类型,是Integer类型的参数,因此,只能传递整型类型的元素,而不能传递String类型的元素

2.ArrayList(Collection<? extends E> c)

观看这个构造方法的源码,它的参数是一个Collection接口类型的参数,表示只要实现了这个接口的,都是可以传参的

?:表示通配符 ,表示的是要传递的参数类型,这个通配符以继承 E 类为上界 ,即必须是 E 类或者 E 类的子类。

示例:

将list引用作为构造方法参数,而list是ArrayList<Integer>类型,即作为参数传递后,向上转型编变成了 Collection<? extends E>类型,根据类型推导,E就是Integer类型,?就是Integer,而在list引用中,本身就初始化了一些元素,那么当它作为参数传递给另一个构造方法时,会将这个元素也默认传递过去。

看运行结果,它会将自身增加的和其他的类的原来就有的元素打印出来:

如果这个构造方法参数不是继承于Integer类的,会编译报错:

无参数构造方法

观看无参数构造方法的源码:也就是没有初始化数组容量的构造方法,此时的数组是一个空数组,即长度为0,源码中也是将该无参构造方法赋值为一个空数组:

示例:

问题:这个无参构造方法,其实并没有给分配内存,那么为什么还可以add新增数组元素呢?

解决这个问题,我们先看看add方法的源码:

总结来说,就是在第一次add的时候,分配内存空间大小默认是10,如果后边add的时候,发现满了,那么就是在原始内存空间大小的基础上1.5倍进行扩容,即在原始内存空间大小的基础上增加5个内存空间;即顺序表会自动扩容。

五、ArrayLIst的常见操作

|----------------------------------------------|---------------------------|
| 方法 | 解释 |
| boolean add(E e) | 尾插 e |
| void add(int index,E element) | 将 e 插入到 index 位置 |
| boolean addAll(Collection<? extends E> c) | 尾插 c 中的元素 |
| E remove(int index) | 删除 index 位置元素 |
| boolean remove(Object o) | 删除遇到的第一个 o |
| E get(int index) | 获取下标 index 位置元素 |
| E set(int index,E element) | 将下标 index 位置元素设置为 element |
| void clear() | 清空 |
| boolean contains(Object o) | 判断 o 是否在线性表中/线性表中是否包含 o |
| int indexOf(Object o) | 返回第一个 o 所在下标 |
| int lastindexOf(Object o) | 返回最后一个 o 的下标 |
| List<E> sublist(int fromIndex,int toIndex) | 截取部分 list |

boolean addAll(Collection<? extends E> c)尾插 c 中的元素

示例:

运行结果:

boolean remove(Object o)删除遇到的第一个 o

示例:

运行结果:

为什么上述的代码中会出现一道红色的线呢?------ 其实这代表这个方法现在已经很少去使用了。

List<E> sublist(int fromIndex,int toIndex)截取部分 list

示例:

运行结果:

思考:使用sublist方法,是在原顺序表上进行截取呢,还是会重新创建一个顺序表,然后再在这个顺序表上截取呢?

我们可以用代码来验证,使用set方法在test中增加一个元素,然后再次打印一下list的内容,看看截取到的内容还是不是[1,2,3]

我们看运行的结果:

这就说明,使用sublist方法截取是在原来的顺序表中进行截取的。

即 subList()返回的是原列表指定范围的视图,它们共享底层数据存储。

六、ArrayList的遍历

ArrayList 可以使用三种方式遍历:for循环+下标、for-each、使用迭代器

1. for循环

需要使用到size()、get()方法

运行结果:

2. for-each遍历

运行结果:

3. 使用 iterator 迭代器遍历

我们看看iterator的源码:它的返回值是一个泛型类

如果直接打印,会是一串地址:

那么,如何打印内容呢?

------ 需要用到 hasNext方法和 next方法。

hasNext() 和 next()

这两个方法的作用:

比如,有一组数据 1 2 3 4 5,当使用 hasNext 方法检测到下一个位置有元素时,再使用 next 方法可以返回这个 下一个位置元素 ,一直循环访问,知道结束。

运行结果:

4. 使用 ListIterator 迭代器遍历

运行结果:

使用 LIstIterator 迭代器扩展
hasPrevious() 和 previous()

这两个方法的作用:

注意:是从列表的最后一个元素的后一个位置开始遍历的,也就是反向遍历。

运行结果:

一道练习题

题目:删除第一个字符串中出现的所有第二个字符串中出现的字符

使用 列表list 的方式解决。

示例:输入: s1 = hello world s2 = eord

输出: list = hll wl

思路:创建一个列表,使用 contains 方法,它的作用是判断该元素是否在线性表中/线性表中是否包含该元素。

如果第二个字符串中包含第一个字符串中的字符,就不add放入如列表中,否则,放入列表中,然后返回列表。

注意:contains方法的返回值是String类型,ArrayList类的参数是Character字符类型(因为列表中存储的是一个个字符)

运行结果:

如果运行结果不想要有 ,的出现,可以使用size和get方法将列表中的内容一个个打印出来:

运行结果:

相关推荐
鱼跃鹰飞15 分钟前
面试题:解释一下什么是全字段排序和rowid排序
数据结构·数据库·mysql
yaoxin52112317 分钟前
292. Java Stream API - 使用构建器模式创建 Stream
java·开发语言
阮松云24 分钟前
code-server 配置maven
java·linux·maven
木木木一29 分钟前
Rust学习记录--C11 编写自动化测试
java·学习·rust
bug总结32 分钟前
uniapp+动态设置顶部导航栏使用详解
java·前端·javascript
a努力。37 分钟前
字节跳动Java面试被问:一致性哈希的虚拟节点和数据迁移
java·开发语言·分布式·算法·缓存·面试·哈希算法
qq_3181215937 分钟前
互联网大厂Java面试故事:支付与金融服务微服务架构、消息队列与AI风控全流程解析
java·spring boot·redis·微服务·kafka·支付系统·金融服务
文慧的科技江湖43 分钟前
重卡的充电桩一般都是多少千瓦? - 慧知开源充电桩平台
java·开发语言·开源·充电桩开源平台·慧知重卡开源充电桩平台
短剑重铸之日1 小时前
《7天学会Redis》Day 3 - 持久化机制深度解析
java·redis·后端·缓存
独自破碎E1 小时前
【前序+中序】重建二叉树
java·开发语言