2. 容器

  1. java 容器都有哪些?
    https://blog.csdn.net/weixin_42574142/article/details/87125363

    截屏2020-06-22上午10.53.08.png

  2. Collection 和 Collections 有什么区别?
    java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set
    Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

  3. List、Set、Map 之间的区别是什么?


    截屏2020-06-22上午10.58.06.png
  4. HashMap 和 Hashtable 有什么区别?
    https://blog.csdn.net/woshimaxiao1/article/details/83661464

  • 继承的父类不同:hashMap 继承abstractMap,hashTable继承dictionary类。
  • contains方法:HashMap删除了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
  • 同步:HashTable同步,HashMap非同步。
  • 空值:HashMap允许空键值,HashTable不允许。
  1. 如何决定使用 HashMap 还是 TreeMap?
    HashMap基于哈希表实现,HashTree基于红黑树实现。
    在Map中插入删除定位等操作用HashMap,对有序的key进行遍历用TreeMap。

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


    截屏2020-06-27下午3.22.18.png
  • 概述:HashMap是基于哈希表的继承了Map接口的非同步实现,提供所有可选的映射操作。允许null键null值。不保证映射的顺序。
  • 数据结构:实际上是一个散列表数据结构,也就是数组和链表的结合体。
  • put元素的过程:首先散列表为空,此时需要给列表赋值一个初试值大小,默认16,还有阈值,是散列表大小*装填因子。
    put一个键值对,
    1)先计算key的哈希值。是如何计算key的哈希值的?


    image

为什么要这样干呢??我们一般来说直接将key作为哈希值不就好了吗,做异或运算是干嘛用的??

将key的哈希值的高位也做了运算(与高16位做异或运算,使得在做&运算时,此时的低位实际上是高位与低位的结合),这就增加了随机性,减少了碰撞冲突的可能性

2)判断哈希表的位置是否为空,为空直接插入。
3)哈希表位置不为空,判断key是否一样,一样的话直接覆盖。
4)哈希表位置不为空,key值也不一样,看哈希表这个位置-treetable[i]是否为红黑树,如果已经是红黑树,直接插入;

不是红黑树,看此处链表长度是否大于8且表容量大于64,如果符合,转成红黑树插入;不符合,不符合链表插入;

5)判断链表大小是否大于threshold,大于的话扩容,为原来的两倍。

为何HashMap的数组长度一定是2的次幂?
如果数组进行扩容,数组长度发生变化,而存储位置 index = h&(length-1),index也可能会发生变化,需要重新计算index。
扩容后把老数组遍历扔到新数组中,我们的数组索引位置的计算是通过 对key值的hashcode进行hash扰乱运算后,再通过和 length-1进行位运算得到最终数组索引位置
HashMap的数组长度一定保持2的次幂,比如16的二进制表示为 10000,那么length-1就是15,二进制为01111,同理扩容后的数组长度为32,二进制表示为100000,length-1为31,二进制表示为011111。从下图可以我们也能看到这样会保证低位全为1,而扩容后只有一位差异,也就是多出了最左位的1,这样在通过 h&(length-1)的时候,只要h对应的最左边的那一个差异位为0,就能保证得到的新的数组索引和老数组索引一致(大大减少了之前已经散列良好的老数组的数据位置重新调换)

截屏2020-06-22下午4.37.40.png

截屏2020-06-27下午3.37.38.png

截屏2020-06-27下午3.46.31.png
  1. 说一下 HashSet 的实现原理?
    https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484165&idx=1&sn=fe2aaa3ced88e9fbe153f339be695797&chksm=ebd74204dca0cb12f2b2c7988adf778b1d828ec15543556dd917235c3d97d343fe8827a951bd&scene=21###wechat_redirect

    • HashSet底层由HashMap实现
    • HashSet的值存放于HashMap的key上
    • HashMap的value统一为PRESENT
  2. ArrayList 和 LinkedList 的区别是什么?
    最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

  3. 如何实现数组和 List 之间的转换?

  • List转换成为数组:调用ArrayList的toArray方法。
 List testList = new ArrayList(){{add("aa");add("bb");add("cc");}};
String[] array2 = testList.toArray(new String[testList.size()]);
  • 数组转换成为List:调用Arrays的asList方法。
ArrayList arrayList = new ArrayList(Arrays.asList(arrays));
  1. ArrayList 和 Vector 的区别是什么?
  • Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。
  • ArrayList比Vector快,它因为有同步,不会过载。
  • ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。
  1. Array 和 ArrayList 有何区别?
  • Array定义时就要先声明大小
  • Array可以容纳基本类型和对象,ArrayList只能是对象
  • 功能方面
  1. 在 Queue 中 poll()和 remove()有什么区别?
    poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

  2. 哪些集合类是线程安全的?

  • vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
  • stack:堆栈类,先进后出。
  • hashtable:就比hashmap多了个线程安全。
  • enumeration:枚举,相当于迭代器。
  1. 迭代器 Iterator 是什么?
    迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

  2. Iterator 怎么使用?有什么特点?
    Java中的Iterator功能比较简单,并且只能单向移动:
    (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
    (2) 使用next()获得序列中的下一个元素。
    (3) 使用hasNext()检查序列中是否还有元素。
    (4)使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素.

  1. Iterator 和 ListIterator 有什么区别?
    https://blog.csdn.net/weixin_39241397/article/details/79687789
import java.util.*;
public class TestListIterator{
 
    public static void main(String[] args) {
 1       ArrayList a = new ArrayList();
 2       a.add("aaa");
 3       a.add("bbb");
 4       a.add("ccc");
 5       System.out.println("Before iterate : " + a);
 6       ListIterator it = a.listIterator()
 7       while (it.hasNext()) {
 8           System.out.println(it.next() + ", " + it.previousIndex() + ", " + it.nextIndex());
 9       }
10        while (it.hasPrevious()) {
11            System.out.print(it.previous() + " ");
12        }
13        System.out.println();
14        it = a.listIterator(1);//调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。
15        while (it.hasNext()) {
16            String t = it.next();
17            System.out.println(t);
18            if ("ccc".equals(t)) {
19                it.set("nnn");
20            } else {
21                it.add("kkk");
22            }
23        }
24        System.out.println("After iterate : " + a);

(1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
(4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

  1. 如何保证一个集合不被修改?
    https://blog.csdn.net/W_317/article/details/104979338
    Colelctions工具包的Collections.unmodifiableMap.

comparable 和 comparator:
https://www.cnblogs.com/skywang12345/p/3324788.html

你可能感兴趣的:(2. 容器)