Java中常用的集合及方法(1)

在Java(JDK8)中,集合(Collection)是数据结构的实现,用于存储和操作对象集合。

集合(Collection)中包含的一般类或接口:

在这其中呢,我们经常使用的其实就是List、Set、Queue这三个接口及其实现类,那我们分别介绍一下这些接口/类的常用方法和使用中需要注意的地方:

1、List

List 是Java集合框架中的一个接口,它代表一个有序的集合(也称为序列)。List接口中的元素允许重复,并且元素具有索引,即每个元素都有一个特定的位置,可以通过索引来访问。它定义了一组有序的、可重复的、可以包含null元素、并允许通过索引位置访问和操作其中的元素的集合

1.1 使用场景

  • 需要维护元素的插入顺序,即列表的顺序与其添加元素的顺序一致。
  • 通常用于需要频繁进行增删改查操作,尤其是根据索引进行操作的情况。
  • 需要支持按索引查找、迭代遍历或存储有序数据集的应用场景。

1.2 作用

  • 提供了丰富的API来实现对列表元素的各种操作,如添加、删除、修改和查询等。
  • 支持通过索引快速访问列表中特定位置的元素,时间复杂度为O(1)(对于ArrayList而言)。
  • 允许重复元素,并且保持元素的插入顺序。

1.3 常用的实现类

  • ArrayList:基于动态数组实现,适用于随机访问和遍历,插入和删除操作在非尾部时可能效率较低,因为涉及数组元素的移动。
  • LinkedList:基于双向链表实现,插入和删除操作在任何位置都较为高效,但随机访问的时间复杂度较高(O(n))。
  • Vector:类似于ArrayList,但是线程安全,但在多线程环境下性能较差,不推荐在新的代码中使用,可以考虑使用CopyOnWriteArrayList替代以保证线程安全性。

1.3.1 Vector和ArrayList的区别:

Vector和ArrayList主要区别在于线程安全、性能和扩容策略方面

从线程安全的角度来看,Vector是线程安全的,因为它的方法使用了synchronized关键字来实现同步,而ArrayList则不是线程安全的。这意味着在多线程环境下,使用Vector不需要额外的同步措施,而ArrayList则需要外部同步来保证数据的一致性。

在性能方面,由于ArrayList没有使用synchronized加锁,它的处理速度通常会更快。这是因为synchronized会带来一定的性能开销,尤其是在高并发的情况下。

两者在扩容策略上也有所不同。当需要增加容量时,Vector默认会将容量翻倍,而ArrayList则是增加50%的容量。这种差异影响了它们在面对大量数据插入时的性能表现。

在实际开发中多线程编程更倾向于使用Collections.synchronizedList()方法来包装一个ArrayList,或者使用CopyOnWriteArrayList(适用于读多写少的场景)来替代Vector,这样可以更好地平衡线程安全性和性能。在实际开发中,直接使用Vector的情况相对较少。

1.3.2 ArrayList和LinkedList的区别

ArrayList和LinkedList的主要区别在于它们的底层数据结构、随机访问效率以及插入和删除操作的效率

从底层数据结构来看,ArrayList是基于动态数组实现的,而LinkedList则是基于双向链表实现的。这意味着ArrayList在内存中是连续存储的,而LinkedList则是通过节点和指针来存储元素。

在随机访问效率方面,ArrayList通常优于LinkedList。因为ArrayList可以直接通过数组下标快速定位到元素,而LinkedList需要从头或尾遍历节点直到找到目标元素,这在时间复杂度上是线性的。

在插入和删除操作的效率上,LinkedList通常比ArrayList更胜一筹。这是因为ArrayList在插入和删除时可能需要进行数组的扩容和元素的复制,而LinkedList只需要修改相应的指针即可完成操作,这在时间复杂度上更为高效。

两者在内存空间占用上也有所不同。ArrayList由于是连续存储,可能会有更大的内存开销,尤其是在列表规模较大时。而LinkedList由于需要额外的节点信息来存储指针,也会有一定的内存开销。

简单的说,ArrayList适合需要快速随机访问和较少插入删除操作的场景,而LinkedList适合需要频繁插入删除操作且对随机访问要求不高的场景。在实际开发中,应根据具体需求和性能考量来做出选择。

1.4 常用的方法

  • 添加元素:add(E element)add(int index, E element)、addAll(Collection<? extends E> c)
  • 删除元素:remove(Object o)remove(int index)
  • 修改元素:set(int index, E element)
  • 查询元素:get(int index)
  • 判断是否包含某个元素:contains(Object o)
  • 清空列表:clear()
  • 获取列表大小:size()
  • 排序:sort(List<T> list)(Java 8及以上版本,调用Collections.sort方法)
  • 翻转列表:Collections.reverse(list)
  • 查找索引:indexOf(Object o)lastIndexOf(Object o)
  • 子列表:subList(int fromIndex, int toIndex)

1.5 使用时需要注意的问题:

  1. 线程安全性List接口本身不是线程安全的,如果多个线程同时修改List,可能会导致数据不一致。需要外部同步或使用线程安全的实现类(如VectorCopyOnWriteArrayList)。
  2. 性能:不同的List实现类有不同的性能特点。例如,ArrayList在随机访问时较快,但在中间位置插入和删除元素时较慢;而LinkedList在插入和删除时较快,但随机访问较慢。根据使用场景选择合适的实现类。
  3. 索引越界:在使用getsetremove方法时,如果提供的索引超出列表的范围(小于0或大于等于列表大小),将会抛出IndexOutOfBoundsException异常。
  4. 元素类型:向List中添加的元素必须与声明的类型一致,否则在运行时可能会抛出ClassCastException异常。
  5. 空指针异常:如果向List中添加null元素,并且后续代码中没有对null进行适当处理,可能会导致NullPointerException异常。

具体的方法示例:后续跟进补充。。。

  • 37
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值