Exception in thread “main“ org.apache.ibatis.binding.BindingException: Invalid bound state问题解决记录

FileItem中文名字乱码问题的解决

  返回  

java集合-面试题

2021/8/21 11:07:11 浏览:

1、Iterator和ListIterator有什么区别?
2、Java中已经有数组类型,为什么还要提供集合?


1、Iterator和ListIterator有什么区别?

  1. 首先ListIterator继承与Iterator,相较于Iterator扩展了很多方法
    • add(E e); hasPervious(); pervious(); perviousIndex(); nextIndex();等方法
  2. 使用范围不同:Iterator能够变量所有集合,ListIterator只能遍历List集合

2、Java中已经有数组类型,为什么还要提供集合?

无非就是考察数组和集合的优缺点

  1. 数组的优点:
    1. 数组的效率要高于集合,因为集合是对数组进行了封装,效率始终不会超过数组
    2. 数组能够存放基本数据类型,而集合只能存放引用类型,因为集合中有泛型约束,只能是Object类型
  2. 数组的缺点:
    1. 不是面向对象的,存在明显缺陷
    2. 数组的长度一旦确定就无法改变,而集合是动态数组
    3. 数组无法直接获取其中存储了多少个元素,集合可以通过size方法获取
  3. JDK提供集合的意义:
    1. 集合以类的形式存在,更符合面向对象的特点,通过简单的方法调用就可以实现一系列功能
    2. 集合有多种数据结构(数组,链表,数),使用不同场合
    3. 弥补了数组的缺陷,提高开发效率

3、TreeSet的原理是什么?使用时需要注意什么?

  1. TreeSet是基于TreeMap实现的,TreeMap底层是采用红黑树实现的;
  2. 特点:存储有序的,不可重复的数据,添加,删除,判断元素是否存在效率较高
  3. 使用方式:
    1. 如果我们使用的是TreeSet的空参构造方法,那么在TreeSet中存放的元素就要实现Comparable接口的compareTo()方法,(自然排序),否则就会抛异常
    2. 此外支持TreeSet的构造方法指定Comparator接口(定制排序)

4、HashSet的实现原理?有什么特点?

  1. 首先HashSet线程不安全,存储无序的不可重复的数据,底层采用HashMap存储,所以HashSet的特点和HashMap中key的特点一致
  2. 因为HashSet底层是通过HashMap存储的,HashMap中的key存储的是无序的不可重复的数据,所以HashSet实际上就是将元素存储在底层HashMap的key位置上,而所有元素(key)对应的value则引用一个全局静态常量Object(这样就可以节省资源);
  3. HashSet和HashMap的key一样可以存储null值,且仅能存储一个null
  4. HashSet在存储元素时,元素需要重写hashCode()、equals()方法,用来确保数据的唯一性;
    HashSet判断数据是否相等的条件,和key一样:先判断hash是否相等,在判断元素内容是否相等(地址和equals返回值);

5、ArrayList和LinkedList哪个插入性能更高?

  1. 首先不同情况下两者的插入性能是不一样的,整体上看LinkedList的插入性能更高(对于频繁、顺序插入而言)

第一种情况:涉及ArrayList扩容的情况一旦 ArrayList 扩容机制触发那么,效率降低大大降低,也就低于LinkedList了

第二种情况:不涉及ArrayList扩容情况;

  1. 顺序插入:两种的性能相差无几,因为都是在最后插入
  2. 随机插入[add(int, E)]:
    1. ArrayList底层采用的数组,随机访问效率高,但是插入效率低(要将插入位置后面的元素后移);
    2. LinkedList底层采用的链表,随机访问需要变量,找到index下标的元素,访问效率低,但是插入效率高;
    3. 所以对于随机插入来说,两者的效率高低无法确定

这里我们来扩展一下LinkedList中add()方法源码分析

public void add(int index, E element) {
    checkPositionIndex(index);	//这步是验证index的合理性

    if (index == size)					//如果是在最后插入,就linkLast
        linkLast(element);
    else
   	    // 这里其实最值得分析的就是node(index)方法了,而linkBefore就是在指定元素前面插入元素
        linkBefore(element, node(index));	
}

// 我们来看一下 node(index) 方法的源码
Node<E> node(int index) {
    // assert isElementIndex(index);
    /*
    这里我们看了一下它的大致思路:
    	先二分找到index属于哪一边,然后再从两端(first端,和last端)遍历
    	所以这里的遍历实际上最多只遍历二分之一就可以了

    	所以我们可以得出:
    	1.如果ArrayList的插入的index,小于二分之一,
    	  那么无论如何,ArrayList的插入效率都要低于LinkedList,
    	  因为ArrayList的始终要移动超过二分之一的元素,而LinkedList只需要遍历不到二分之一,就可以插入了
    */
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

void linkBefore(E e, Node<E> succ) {
    // assert succ != null;
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

6、LinkedHashMap、LinkedHashSet、LinkedList哪个最适合当Stack使用?

当然是

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号