集合框架

  • list, map,set
  • 接口:Collection

list, map,set
这里写图片描述

java.util包下面的所有的集合类都是快速失败fail-fast迭代器的,而java.util.concurrent包下面的所有的类都是安全失败fail-safe迭代器的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。因为安全失败是基于之前的数据进行一份拷贝,所以不受源集合的影响。

  • List

    1. LinkedList 类
      特点:对顺序访问进行了优化,向 List 中间插入与删除的开销并不大。随机访问则相对较慢
      Foreach其实就是在使用迭代器,Iterator中的next()方法采用的是顺序访问方法,因此在LinkedList里使用Iterator较快
    2. ArrayList 类
      ArrayList是实现了基于动态数组的数据结构,随机访问快.
      在ArrayList中是Foreach比迭代器快。
      上述所提到的ConcurrentModficationException是在使用迭代器的时候对集合进行修改才会抛异常,在你迭代之前,迭代器已经被通过list.itertor()创建出来了,如果在迭代的过程中,又对list进行了改变其容器大小的操作,那么Java就会给出异常。但是迭代器在遍历的时候是可以对元素进行删除的,因为迭代器中remove()函数是同步了modCount 与expectedModCount所以不会抛异常
      如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList, 这个是concurrent包下的。如果在使用迭代器 遍历list的时候修改list则会报错。使用迭代器更加线程安全,因为它可以确保,在当前遍历的集合元素被更改的时候,它会抛出ConcurrentModificationException
    3. Vector 类 与ArrayList相比是线程安全
      Stack继承自Vector, 所有pop(),peek(),search()都加了synchronized关键字。search()源自vector的lastIndexOf()它会从尾到头扫描,如果不加同步方法,在多线程环境中有很多个这样的查询操作将会导致性能变差。
  • Queue
    1)阻塞式队列(BlockingQueue)队列满了以后再插入元素则会抛出异常,主要包括ArrayBlockQueue、PriorityBlockingQueue,
    LinkedBlockingQueue。
    2)双端队列Deque:支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。

  • Set

    1. HashSet 类 为快速查找设计的 Set
    2. LinkedHashSet 类:具有 HashSet 的查询速度,且内部使用链表维护元素的顺序 ( 插入的次序 ) 。于是在使用迭代器遍历 Set 时,结果会按元素插入的次序显示
    3. TreeSet 类保存次序的 Set, 底层为树结构。使用它可以从 Set 中提取有序的序列。
  • Map

    1. Map 也有内置的排序,因而不关心元素添加的顺序。如果添加元素的顺序对你很重要,应该使用 LinkedHashSet 或者 LinkedHashMap.
    2. HashMap 就是使用对象的 hashCode() 进行快速查询的。此方法能够显著提高性能。注意key要是不可变对象,否则有可能改变hashcode。当我们通过传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,然后使用equals()方法找出正确的Entry,然后返回它的值。
      HashMap的底层实现主要是借助数组+链表+红黑树来实现。Vector、HashTable等集合类效率比较低但都是线程安全的。
      包java.util.concurrent下包含了大量线程安全的集合类,效率上有较大提升。
      put操作:首先通过hashCode获得对应的三列桶,其次通过遍历看是否equals获得链地址上有无此元素,有则替换,无则增加到头的那个地方,null总是在最前面,而且仅仅保留一个null。
      get操作:类似。因为get的时候会判断hashcode是否相同,然后equals是否,所以必须要设置key为不可变。
      rehash过程 Entry[]的长度一定后,随着map里面数据的越来越长,超过了加载因子,必须调整table的大小。每次将数组拓展到原来数据长度的两倍。
      解决hash冲突:再hash,链地址发,开放地址法.
    3. ConcurrentHashMap 高并发的版本不像hashtable加锁影响性能。通过将hashmap分成很多片小的segment,每个segment都枷锁,来提高性能。 LinkedHashMap,TreeMap类似
    4. WeakHashMap 表示弱键映射,允许释放映射所指向的对象。这是为了解决某类特殊问题而设计的,如果映射之外没有引用指向某个“键”,则“键”可以被垃圾收集器回收。
    5. IdentityHashMap 使用==代替equals() 对“键”进行比较的散列映射。专为解决特殊问题而设计。

接口:Collection
Collection有一个重要的方法:iterator(),返回一个Iterator(迭代器),用于遍历集合的所有元素,我们不需要关心到底是哪种Iterator,它只需要获得这个Iterator接口即可,这就是接口的好处,面向对象的威力。
Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者在迭代过程中移除元素。

对于并发控制而言,锁是一种悲观策略,会阻塞线程执行,而无锁是一种乐观策略
HashMap是非线程安全的,在多线程环境还是需要用到hashtable,concurrenthashmap或者打包成同步map类,这其中concurrenthashmap性能最佳,但是其本质用到了互斥锁,或多或少会影响性能,或者造成死锁. 这时候可以考虑无锁,用到了CAS compareAndSwap,比如链表的插入操作,在插入之前先检查前节点是否指向它的下一个节点(考虑到多线程的影响),具体是用for循环做一个compareAndSwap的方法直到满足为止.这就是atomic原子性操作,但是这种方式只能保证一个变量保持这种原子性,多个的话就要另想它法.
应用:
jdk中
java.util.concurrent.atomic包,比如AtomicInterger这种都是用的CAS技术,无锁队列java.util.concurrent.ConcurrentLinkedQueue,跳跃表java.util.concurrent.ConcurrentSkipListMap.
  jvm中
  单线程环境中可以通过直接查看空闲表去分配,而多线程环境中,由于再给一个对象分配内存的时候不是原子性的操作,至少需要以下几步:查找空闲列表、分配内存、修改空闲列表等等,这是不安全的.虚拟机采用CAS配合上失败重试的方式保证更新操作的原子性.
  多线程环境更好的策略是:每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲区(TLAB),线程内部需要分配内存时直接在TLAB上分配就行,避免了线程冲突。只有当缓冲区的内存用光需要重新分配内存的时候才会进行CAS操作分配更大的内存空间。

Comparable & Comparator
Collections中有两种方法实现sort(稳定排序 基数排序),
public static <T extends Comparable<? super T>> void sort(List<T> list)方法某个类实现Comparable接口,
public static <T> void sort(List<T> list, Comparator<? super T> c)需要一个Comparator比较器。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值