208面试题 容器

二、容器

18.java 容器都有哪些?

| Collection
|  ├ List
|  │-├ LinkedList
|  │-├ ArrayList
|  │-└ Vector
|  │ └ Stack
|  ├ Set
|  │├ HashSet
|  │├ TreeSet
|  │└ LinkedSet
|
| Map
  ├ Hashtable
  ├ HashMap
  └ WeakHashMap

19.Collection 和 Collections 有什么区别?

Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
主要区别:Collections 是一个包装类,Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许,一些 collection 是有序的,而另一些则是无序的。

20.List、Set、Map 之间的区别是什么?
比较ListSetMap
继承接口CollectionCollection
常见实现类AbstractList(其常用子类有ArrayList、LinkedList、Vector)AbstractSet(其常用子类有HashSet、LinkedHashSet、TreeSet)HashMap、HashTable
常见方法add( )、remove( )、clear( )、get( )、contains( )、size( )add( )、remove( )、clear( )、contains( )、size( )put( )、get( )、remove( )、clear( )、containsKey( )、containsValue( )、keySet( )、values( )、size( )
元素可重复不可重复(用equals()判断)不可重复
顺序有序无序(实际上由HashCode决定)
线程安全Vector线程安全Hashtable线程安全
21.HashMap 和 Hashtable 有什么区别?
  1. hash数组初始化时机不同,Hashtable是在构造函数初始化,而HashMap是在第一次put()初始化hash数组。
  2. 在HashTable中,hash数组默认大小是11,增加的方式是old2+1。在HashMap中,hash数组默认大小是16,增加的方式是2old而且一定是2的整数.
  3. HashMap允许空(null)键值(key),而HashTable不允许。
  4. HashMap把Hashtable的contains()方法去掉了,改成了containsvalue()和containsKey()。
  5. Hashtable的方法是线程安全的,而HashMap不支持线程的同步,不是线程安全的。
  6. Hashtable使用Enumeration,HashMap使用Iterator。
  7. hash值的使用不同,HashTable直接使用对象的hashCode。
22.如何决定使用 HashMap 还是 TreeMap?

对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。

23.说一下 HashMap 的实现原理?

HashMap:HashMap基于Map接口实现,元素以键值对的方式存储,并且允许使用null值,因为key不允许重复,因此只能由一个键为null,另外HashMap不能保证放入元素的顺序,它是无序的,和放入的顺序并不相同.HashMap是线程不安全的。HashMap的扩容是一项非常耗时的任务,所以如果能估算Map的容量,最好给他一个默认的初始值,避免过多扩容。HashMap是线程不安全的,多线程环境是不安全的,多线程环境推荐使用ConcurrentHashMap。JDk1.8对HashMap的实现方式进行了一些改变,由数组+链表的方式变化为数组+链表+红黑树的存储方式
简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

24.说一下 HashSet 的实现原理?
  1. 是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
  2. 当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
  3. HashSet的其他操作都是基于HashMap的。
25.ArrayList 和 LinkedList 的区别是什么?

共性:ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只是实现的方式有所不同。
区别:List接口的实现方式不同
ArrayList实现了List接口,以数组的方式来实现的,因此对于快速的随机取得对象的需求,使用ArrayList实现执行效率上会比较好。
LinkedList是采用链表的方式来实现List接口的,因此在进行insert和remove动作时效率要比ArrayList高。适合用来实现Stack(堆栈)与Queue(队列)。

26.如何实现数组和 List 之间的转换?
一、List转数组

方法一、使用for循环

//要转换的list集合 
List testList = new ArrayList(){{add(“aa”);add(“bb”);add(“cc”);}};
//初始化需要得到的数组
    String[] array = new String[testList.size()];

    //使用for循环得到数组
    for(int i = 0; i < testList.size();i++){
        array[i] = testList.get(i);
    }

    //打印数组
    for(int i = 0; i < array.length; i++){
        System.out.println(array[i]);
    }

方法二、使用toArray()方法

//要转换的list集合
 List<String> testList = new ArrayList<String>(){{add("aa");add("bb");add("cc");}};

 //使用toArray(T[] a)方法
 String[] array2 = testList.toArray(new String[testList.size()]);

//打印该数组
  for(int i = 0; i < array2.length; i++){
      System.out.println(array2[i]);
  }
二、数组转List

方法一、使用for循环

 //需要转换的数组
   String[] arrays = new String[]{"aa","bb","cc"};

   //初始化list
   List<String> list = new ArrayList<String>();

   //使用for循环转换为list
   for(String str : arrays){
       list.add(str);
   }

   //打印得到的list
  System.out.println(list);

方法二、使用asList()

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arrays));

方法三、使用asList()

List<String> list = Arrays.asList(arrays);
同方法二一样使用了asList()方法。这不是最好的,因为asList()返回的列表的大小是固定的。事实上,返回的列表不是java.util.ArrayList,而是定义在java.util.Arrays中一个私有静态类。我们知道ArrayList的实现本质上是一个数组,而asList()返回的列表是由原始数组支持的固定大小的列表。这种情况下,如果添加或删除列表中的元素,程序会抛出异常UnsupportedOperationException。

方法四、使用Collections.addAll()

List<String> list2 = new ArrayList<String>(arrays.length);
Collections.addAll(list2, arrays);
27.ArrayList 和 Vector 的区别是什么?

(1):Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
(2):ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
(3):Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。

28.Array 和 ArrayList 有何区别?

1、存储内容比较
Array 数组可以包含基本类型和对象类型,
ArrayList 却只能包含对象类型。
Array 数组在存放的时候一定是同种类型的元素。ArrayList 就不一定了 。
2、空间大小比较:
Array 数组的空间大小是固定的,所以需要事前确定合适的空间大小。
ArrayList 的空间是动态增长的,而且,每次添加新的元素的时候都会检查内部数组的空间是否足够。
3.方法上的比较:
ArrayList 方法上比 Array 更多样化,比如添加全部 addAll()、删除全部 removeAll()、返回迭代器 iterator() 等。

29.在 Queue 中 poll()和 remove()有什么区别?

remove()poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null。因此新的方法更适合容易出现异常条件的情况。

30.哪些集合类是线程安全的?
  • Vector:就比Arraylist多了个同步化机制(线程安全)。
  • Hashtable:就比Hashmap多了个线程安全。
  • ConcurrentHashMap:是一种高效但是线程安全的集合。
  • Stack:栈,也是线程安全的,继承于Vector。
31.迭代器 Iterator 是什么?

Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包括了可以返回迭代器实例的迭代方法。迭代器可以在迭代过程中删除底层集合的元素,但是不可以直接调用集合的remove(Object obj)删除,可以通过迭代器的remove()方法删除

32.Iterator 怎么使用?有什么特点?

使用:
Java集合类中Map接口下的相关类并没有像Collection接口的相关类一样实现get()方法,因此在要实现遍历输出的场景中没法直接用get()方法来取得对象中的数据,但Java本身提供了另一种遍历数据的方法,即用Iterator迭代器,虽然Iterator可以用来遍历读取数据,但它本质上不是一种方法,它只是一种设计模式,它是一个对象,一个“轻量级”的对象。
特点:

  1. Iterator遍历集合元素的过程中不允许线程对集合元素进行修改,否则会抛出ConcurrentModificationEception的异常。
  2. Iterator遍历集合元素的过程中可以通过remove方法来移除集合中的元素。
  3. Iterator必须依附某个Collection对象而存在,Iterator本身不具有装载数据对象的功能。
  4. Iterator.remove方法删除的是上一次Iterator.next()方法返回的对象。
  5. 强调以下next()方法,该方法通过游标指向的形式返回Iterator下一个元素。
33.Iterator 和 ListIterator 有什么区别?
  1. ListIterator有add()方法,可以向List中添加对象,而Iterator不能
  2. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
  3. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
  4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
34.怎么确保一个集合不能被修改?

在作为参数传递之前,我们可以使用Collections.unmodifiableCollection(Collection c)方法创建一个只读集合,这将确保改变集合的任何操作都会抛出UnsupportedOperationException。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值