Java容器

  1. 说说常见的集合有哪些?
    • 实现Collection接口的集合:
      • 实现List的集合:
        •  ArrayList:以数组的类型进行存储,线程不安全,查询效率高,添加删除效率低(因为会对数组中的元素进行移动)
        • LinkedList:以双向链表的类型进行存储,线程安全,查询效率低(因为需要双向遍历),添加删除效率高(因为只需要记录前后两个元素)
        • vector:以数组的类型进行存储,线程安全,查询效率高,添加删除效率低----------->现在不推荐使用,因为扩容只扩容1倍,而且只能在尾部进行插入与删除,效率太低,所以应使用java.util.concurrent.CopyOnWriteArrayList,也是线程安全的
        • stack:vector的子类,特点是先进后出
      • 实现set的集合:
        • HashSet:无序且不可重复,集合元素可以为null,在进行遍历输出时可能不会按照添加顺序进行输出,重复是通过equals方法判断对象是否相等
        • LinkedHashSet:根据元素的HashCode值决定元素存储位置,并且使用双向链表进行维护元素的次序,在进行遍历输出时会按照添加的顺序进行输出。遍历效率比HashSet高,但插入效率比HashSet低
        • TreeSet:实现了SortedSet接口,遍历时会将添加的元素排序输出
    • 实现Map的接口的集合:
        • HashMap:以键值对(key,value)的方式进行存储,线程不安全,键值对key、value的值能为null,继承AbstractMap
        • HashTable:以键值对(key,value)的方式进行存储,线程安全(所有方法都使用了synchronize修饰),键值对不能为null,继承Dictionary
        • TreeMap:以红黑树的类型进行有序的存储,自己可以自定义排序器
        • ConcurrentHashMap:线程安全,比HashTable效率高
  2. HashMap的实现原理?
    • HashMap基于hash算法实现的,通过put(key,Value)存储,get(key)获取。当使用put进行存储时,HashMap会根据key的HashCode()计算出的hash值,根据hash值将value存储到bucket中。当计算出存在hash冲突时,HashMap的做法是使用链表和红黑树进行存储相同hash值的value
  3. HashSet的实现原理?
    • HashSet是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,可以这样说,HashSet中的元素,只是保存在HashMap的key上,而value使用final static的Object对象标识,所以HashSet的实现比较简单,相关的HashSet的操作,基本上是直接调用HashMap中的方法
  4. HashMap和HashTable之间的区别?
    • HashMap:键值对key-value都能为null,线程不安全,继承AbstractMap
    • HashTable:键值对key-value不能为null,线程安全,继承Dictionary
  5. HashTable和ConcurrentHashMap之间的区别?
    • HashTable实现线程是为所有的方法加上synchronize的修饰,当有一个线程获得了资源锁,在此线程未释放锁时,其他线程都处于阻塞状态,当存储较大时,效率会急剧下降
    • ConcurrentHashMap实现线程是锁的细粒度(分段锁),ConcurrentHashMap将Hash表分为16个桶(默认值),每一把锁只锁容器中的一个桶,多线程访问容器时,就不会存在锁竞争,提高并发访问率
        • ConcurrentHashMap是由Segment数据结构和HashEntry数据结构组成。Segment是一种重入锁ReentranLock,扮演锁的角色。HashEntry存储着键值对数据。Segment的结构和HashMap类似,都是数组加链表的存储方式,一个Segment包含一个HashEntry数组,HashEntry数组内存储链表结构的元素,当需要修改HashEntry数组时,必须首先获得对应的Segment。
  6. HashMap的put()方法的具体流程?
    • HashMap在1.8之前的存储方式是【数组+链表】,1.8之后的存储方式是【数组+链表+红黑树】链表长度>8时,链表转为红黑树
    • 判断HashMap是否为null或者长度是否为0,如果为null或长度为0,则进行resize()扩容
      • resize()扩容是在【length的长度>=[size*扩容因子(0.75)]】时,扩容到原来长度2倍,当长度被扩容到(2^30)时,阈值会被修改为(2^31-1)此后就不会在进行扩容
    • 通过key的hash值与HashMap的长度做与运算获取key的索引,判断索引位置是否为null,如果为null,则直接将数据插入
    • 如果不为null,则进行判断new key是否与old key相同,并且key!=null,相同,则覆盖旧值
    • 如果不相同,则发生了哈希冲突,判断数据结构是树还是链表,是树直接在树中插入或更新
    • 如果是链表,则需要对链表进行遍历,判断链表中next位置是否为null
    • 如果为null则将数据插入链表,然后进行判断是否链表长度length>=7,满足则转为红黑树,将链表所有元素加入到红黑树中
    • 如果不为null,判断new key与old key是否相同,并且key!=null,如果满足,直接覆盖,不满足则继续遍历链表
    • 最后判断扩容,当实际存在的键值对数量>最大容量,就进行扩容
  7. HashMap是如何解决哈希冲突?
    • 哈希:也称"散列",任意输入通过哈希函数处理,输出特定长度的值,这就是哈希值
    • 哈希函数的特点:哈希冲突:通过统一哈希函数得到相同的哈希值,输入值不相同时,就产生了哈希冲突
      • 通过同一哈希函数得到相同的哈希值,输入值不一定相同
      • 通过同一哈希函数得到不同的哈希值,输入值一定不相同
    • HashMap的存储结构是【数组+链表】,解决哈希冲突的办法就是"链地址法"
  8. HashMap中indexFor()方法中h&(length-1)是什么意思?
    • 此方法主要是为了得到key值的索引,X%2^n=X&(2^n-1),因为HashMap的length默认是16(2^5),扩容操作也是扩容到原来的2倍,而且与操作的效率比较高
  9. Collection和Collections的区别?
    • Collection:是集合类的接口,实现此接口的集合有List和Set
    • Collections:是集合类的工具类,提供了一些静态方法实现对各种集合的查询、排序以及线程安全化等操作
  10. ArrayList、vector、LinkedList的存储性和特性?
    • ArrayList和vector都是以数组的方式进行存储,查询效率都很高,插入删除效率因为这两个操作都会涉及数组内元素的移动,所以效率低
    • LinkedList:以双向链表的方式进行存储,查询效率低,因为查询时需要双向遍历链表,但是插入和删除的效率高,因为只需要记录前后元素
  11. 如何实现数组和List之间的转换?
    • 数组-->List:Arrays.toList(Array);
    • List-->数组:List自带的toArray()方法
  12. 在Queue中poll()和remove()有什么区别?
    • 相同点:都是返回Queue中的第一个元素,并且在Queue中将此元素删除
    • 区别:当Queue中没有元素时,poll()会返回null,remove()会抛出异常NoSuchElementException异常
  13. Array和ArrayList有何区别?
    • Array能够存储基本数据类型和对象,ArrayList只能存储对象
    • Array是指定大小的,ArrayList是可以自动扩展的
    • Array的内置方法没有ArrayList多
  14. 如何决定使用HashMap还是TreeMap?
    • HashMap:当你需要在Map中进行插入、删除和查询操作,因为HashMap效率要高
    • TreeMap:当你需要对一个key集合进行排序时
  15. 集合中的迭代器(Iterator)是什么?它有什么特点?
    • Iterator可以遍历任意的Collection接口,在使用一个Collection时可以使用迭代器方法获得迭代器实例。Iterator取代了Java集合框架中的Enumeration,迭代器允许调用者在迭代过程中移除元素(Iterator.remove())
    • Iterator的特点:效率比普通的for循环要高,在当前遍历的集合元素被更改的时候(List.remove()、List.add(String str)等),就会抛出ConcurrentModificationException异常,即并发修改异常。详见:https://blog.csdn.net/sukier_JE/article/details/79898892
  16. Iterator和ListIterator有什么区别?
    • Iterator可以遍历Set和List集合,而ListIterator只能遍历List
    • Iterator只能单向遍历,而ListIterator可以双向遍历
    • ListIterator从Iterator接口继承,解决了并发修改的问题
  17. 怎么确保一个集合不能被修改?
    • 使用Collections.unmodifiableCollection(Collection c)方法来创建一个只读的集合,当对只读集合进行修改时,集合都会抛出java.lang.UnsupportedOperationException异常
  18. 如何遍历HashMap集合?
    • 方式一:获取key集合,通过key值遍历value
    • 方式二:通过Iterator进行遍历map.entrySet()集合
    • 方式三:使用forEach()直接遍历map.entrySet()集合,推荐使用
    •  方式四:直接遍历Value集合,只能遍历value得不到key

转载于:https://www.cnblogs.com/Fmir/p/11308019.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值