Java集合-2 数组,ArrayList,Vector,CopyOnWriteArrayList ,LinkedList

数组

  • 特点
    数组是最基础的数据结构,它会在初始化申请一块连续的固定的内存区域。所以数组的访问速度很快,时间复杂度是O(1),但是由于是固定的区域,所以数组的长度在初始化之后是无法修改的。
  • Arrays
    Arrays是一个便于操作数组的类
    • sort:为数组排序
    • binarySearch:在数组中进行二分查找
    • equals:比较两个数组
    • fill:为数组的每一个元素填充数据
    • copyOf/copyOfRange,复制一个数组
    • asList:将数组转化为List,注意,返回的list是不可修改的只读的,使用add,remove,clear都是无效的。
    • toString:把数组转化为字符串,用于打印输出。

ArrayList

  • 特点
    ArrayList是可变长的数组,实际上当长度不够时,会重新申请一段更大的内存区域用于存放更大的数组。当对ArrayList进行插入和删除的时候,需要对数组其他元素进行移动,代价比较高,因此,ArrayList适合于遍历查询,而不适合插入和删除。
  • 扩容:每次扩容增长约1.5倍,添加第一个元素时,默认未10个元素
    //扩容代码
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

其中

 int newCapacity = oldCapacity + (oldCapacity >> 1);

就是扩容的语句,实际上是原长度+原长度右移一位(相当于除以2).
那为什么是1.5倍呢,大概是如果是2倍的话增长太快,而1.5刚好可以转化为以上的位运算。

扩容非常影响性能,所以如果是已知数据的大约长度,应该设置一个差不多的初始值,避免多次扩容。

List<Integer> arr = new ArrayList<>(10000);

Vector与CopyOnWriteArrayList

  • Vector特点
    Vector和ArrayList一样,只不过Vector支持线程同步,大部分方法都使用synchronized修饰,所以其访问比较慢。

但是Vector不被建议使用,其效率类似于HashTable,都是比较低,可以使用 CopyOnWriteArrayList,CopyOnWriteArrayList使用读写锁的模式。当读的时候,是共享的,任意线程都可以读,但是不能写,当写的时候是排他的,只能一个线程写。这种方式即实现多线程同步的问题,也没有损耗太多的性能。

LinkedList

  • 特点
    LinkedList链表,区别于上面的三种,链表并不申请固定的内存,而是增加一个前驱和后驱的指针,用于查找下一个和上一个元素。因此其查找的时间复杂度时O(n),但是其插入和删除的时间复杂度为O(1),只要修改前后驱的指针就可以了。
  • 堆栈
    List同时也实现了堆栈的功能
    • push,压入数据
    • pop,弹出栈顶的数据
    • peek,返回栈顶数据,但是不删除
  • 双头队列
    同时也实现了双头队列的功能
    • getFirst:获取队头
    • getLast:获取队尾
    • removeFirst:移除队尾
    • removeLast:移除队头
    • addFirst:添加到队头
    • addLast:添加到队尾

Collections

ArrayList,Vector,LinkedList都实现了List接口,Collections是List接口的一个辅组类,提供以下函数

  • binarySearch:二分查找
  • swap:交换元素
  • sort:排序
  • copy:复制
  • fill:填充

fail-fast和fail-safe

当对集合进行遍历时,如果同时修改集合,可能会导致不可预知的后果,为了防止这种后果,java禁止了在循环中修改被循环的对象,这就是快速失败(fail-fast).但是对于多线程的情况下,快速失败会导致性能的问题。
于是,在支持多线程的数据结构中,当对集合进行遍历时,对数据进行修改时,修改的是复制的集合,因此不会触发fail-fast,称之为fail-safe.
fail-safe的缺点是

  • 无法感知被修改的集合,因为遍历的还是未被修改的集合。
  • 需要产生大量额复制对象。

Enumeration 和 Iterator的区别

Enumeration 和 Iterator都用于迭代,但是Enumeration未实现fail-fast机制,因此Enumeration更快,但是不安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值