Java面试题-集合泛型

Java面试题-集合泛型

  1. ArrayList和LinkedList区别?

    List是一个有序的集合,可以包含重复的元素,它继承自Collection,其中ArrayList和LinkedList是List的两个重要的实现类。

    ArrayList是基于索引,可以随机存取的数据结构,获取数据的时间复杂度是O(1),但删除数据需要重排数组中的所有数据,因此删除数据时间开销大。ArrayList的底层实现是Array,数组扩容可以自动实现。

    LinkList的数据结构是一个双链表,在添加和删除元素时具有比ArrayList更好的性能,但在查询和修改元素方面弱于ArrayList。

  2. HashMap和HashTable的区别?

    • 对null的支持不同:

      HashTable的键值均不能为空;HashMap的值可以为空,键最多有一个为空。

    • 对外提供的接口不同:

      HashTable比HashMap多提供了elements()和contains()两个方法。elements()用于返回此HashTable中value的枚举,contains()用于此HashTable是否包含传入的value,作用与containsValue()一致。

    • 父类不同:

      HashMap集成自AbstractMap类,HashTable继承自Dictionary类。

    • 安全性不同:

      HashMap线程不安全,HashTable线程安全。另:ConcurrentHashMap是线程安全的,效率比HashTable高很多倍。

    • 初始容量大小和每次扩容容量大小不同。

    • 计算hash值的方法不同。

  3. Collection和Collections的区别?

    Collection是集合类的上级接口,子接口有Set,List,LinkedList,ArrayList,Vector,Stack,Set;

    Collections是集合类的一个帮助类,包含很多有关集合操作的方法,像是一个工具类为Collection框架服务。

  4. 泛型的作用?

    用于约束集合中存放数据的类型。

  5. List,Set,Map的区别?

    • List(对付顺序的好帮手):List接口存储一组不唯一,有序的对象。

    • Set(注重独一无二的性质):不允许重复的集合。不会有多个元素引用相同的对象。

    • Map(用Key来检索专有的Value):使用键值对进行存取。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复。Value可以是任意值或对象。

  6. Array与ArrayList的区别?

    Array和ArrayList都是用来存储数据的集合。可以认为ArrayList是Array的升级版,ArrayList对底层的数组进行了封装和功能扩展,拥有许多原生数组没有的一些功能。

  7. Map的特点

    键值对存取数据,元素存储无序,不允许出现重复键。

  8. 集合类存放与Java.util包中,主要有哪几种接口

    • Collection:集合基本接口
    • Iterator:迭代器,可以通过迭代器遍历集合中的数据。
    • Map:映射表的基础接口
  9. 什么是List接口?

    List是有序的集合Collection,一共有三个List实现类,分别是ArrayList、LinkedList、Vector。

  10. 说说ArrayList(数组)

    ArrayList是最常用的List实现类,内部是通过数组实现的,允许对元素进行随机访问。缺点是每个元素直接不能有间隔,当数组空间不足时需要将已有的数组数据复制到新的存储空间中。当从ArrayList插入删除元素是,需要对数组中大部分元素进行移动,代价比较高。因此它适合随机查找和遍历,不适合插入和删除。

  11. 说是Vector(数组实现,线程同步)

    Vector底层通过数组实现,它支持线程同步,访问速度较慢。

  12. 说是LinkedList(链表)

    LinkedList用链表结构存取数据,适合数据添加和删除,但不支持随机访问,因此查询和遍历效率低。它提供了专门操作链头和链尾的方法,约束后可以当做栈、队列、堆来使用。

  13. 什么是Set集合?

    Set注重独一无二的性质,用于存取无序元素,值不能重复。判断对象是否相等的本质通过hashCode的值。

  14. 什么是HashSet?(哈希表)

    哈希表存放的是哈希值。HashSet存储元素的顺序是按照哈希值来存的,因此取数据也是根据哈希值来取。元素的哈希值是通过元素的hashCode方法来获取的。HashSet通过hashCode值来确定元素在内存中的位置。

  15. 什么是TreeSet?(二叉树)

    • TreeSet()是使用二叉树的原理对新add()的对象按指定的顺序排序。
    • Integer和String对象支持默认的TreeSet排序,自定义对象若想排序需要实现Comparable接口,并覆写相应的compareTo函数。
  16. 说是LinkedHashSet(HashSet+LinkedHashMap)

    对LinkedHashSet而言,它继承与HashSet、又基于LinkedHashMap来实现的。LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同,因此LinkedHashSet的实现上非常简单,只提供了四个构造方法,并通过传递一个标识参数,调用父类的构造器,底层构造一个LinkedHashMap来实现,在相关操作上与父类HashSet的操作相同,直接调用父类的HashSet方法即可。

  17. HashMap(数组+链表+红黑树)

    HashMap根据键的hashCode值存储数据,大多数情况可以直接定位到它的值,因此访问速度快,但遍历的顺序不确定。HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap。

    Java1.7及以前的HashMap:底层由数组+链表组成。数组中每个元素是一个单向链表。

    Java1.8及以后的HashMap:底层由数组+链表+红黑树组成。当链表元素小于等于8是存储元素方式与Java1.7相同,时间复杂度为O(n);当链表中元素超过8时会将链表转换为红黑树,可以降低时间复杂度为O(logN)。

  18. 说说ConcurrentHashMap

    • Segment段:

      ConcurrentHashMap和HashMap思路差不多,但它额外支持并发操作。整个ConcurrentHashMap由一个个Segment组成,Segment代表“部分”或“一段”的意思,所以很多地方都会讲其描述为分段锁。

    • 线程安全(Segment继承ReentrantLock加锁)

      简单理解就是,ConcurrentHashMap是一个Segment数组,Segment通过继承ReentrantLock来进行加锁,所以每次需要加锁的操作锁住的一个segment,这样只要保证每个Segment是线程安全的,也就实现了全局的线程安全。

    • concurrentLevel:并行级别、并发数、Segment数,默认为16

    • Java8实现:类似HashMap,也引入了红黑树。

  19. HashTable(线程安全)

    HashTable是遗留类,很多映射的常用功能与HashMap类似,不同的是它继承自Dictionary类,并且是线程安全的既任一时间只能由一个线程写HashTable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。

  20. TreeMap(可排序)

    TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以排序指定的比较器,当Iterator迭代器变量TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Compareable接口或者在构造TreeMap传入自定义的Comparator,否则运行时会抛出java.lang.ClassCastException类型异常。

  21. LinkedHashMap(记录插入顺序)

    LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是插入的。也可以在构造时带参数,按照访问次序排序。

  22. 泛型类

    和泛型方法一样,泛型类的类型参数声明包含一个或多个类型参数,参数用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

  23. 类型通配符?

    类型通配符一般是用?代替具体的类型参数。

  24. 类型擦除

    Java中的泛型基本是在编译器这个层次实现的,在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉,这个过程就被称为类型擦除。由泛型附加的类型信息对JVM来说是不可见的。

posted @ 2021-04-13 18:37  1LDK  阅读(84)  评论(0编辑  收藏  举报