一.Arraylist与LinkedList有什么区别?
1、ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高,但是插入和删除操作效率比较低。
2、LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,所以增删的时候其它元素的位置不用移动,增删效率高,但查询时通过指针移动查找,所以查询效率低二.ArrayList与Vector的区别?
1.线程安全问题,vector是java早期就有的,是线程安全的;arraylist是java2才出现,是线程不安全的。因为vector支持多线程操作,所以性能上比不上arraylist
2.集合扩充问题,vector扩容默认增加原来的一倍,Arraylist默认增加原来的0.5倍(vector可以由我们自己设置增长的大小,arraylist没有提供相关方法三.HashSet与TreeSet有什么区别?
1.TreeSet 是二叉树实现的,Treeset中的数据是自动排好序的,不允许放入null值 。
2.HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束 。四.hashmap和hashtable的相同点和区别?
相同:
(1)两者都是基于哈希表实现的 (2)内部也都是通过单链表解决冲突问题 (3)同样实现了序列化和克隆接口区别:
(1)继承的父类不同。AbstractMap和dictionary (2) 线程安全不同,hashmap不同步,hashtable同步 (3)是否提供contains方法,hashmap不提供contains方法而改成了containsValue和containskey避免误解 (4)key和value是否允许null,前者允许(key为null时放在table[0]),后者不允许。 (5)hash值不同,hashtable直接使用对象的hashcode(),而hashmap重新计算hash, (6)初始化容量不同,hashtable默认容量11.hashmap16五.hashmap存数据的过程?
hashmap内部维护一个存储数据的Entry数组,hashmap采用链表解决冲突,每一个Entry本质上是一个单向链表,当准备添加一个键值对时,首先通过hash(key)方法计算哈希值,然后通过indexFor(hash,length)求出对应的存储位置,然后插入该位置对应的链表头中
六.谈谈fail-fast机制?
fial-fast机制是集合中的一种错误机制,当多个线程对同一个集合的内容进行操作时,就可能发生fail-fast事件。例如一个线程对某个集合进行访问的过程,该集合的内容被其它线程修改了,就会抛出currentModificationException异常,产生fail-fast事件。
原理:每次调用next方法,在实际访问前,都会调用checkformodification方法,该方法会检查当前的Modcount值和预期的Modcount值是否相等,如果不等就会抛currentModificationException异常七.怎样避免fial-fast?
(1)在单线程遍历过程中,如果要进行remove操作,可以调用迭代器的remove方法而不是集合的remove方法,(因为迭代器的remove方法不能指定元素,只能remove当前遍历过的那个元素,所以调用该方法不会发生fail-fast现象)
(2)使用java并发包(java.util.concurrent)中的类来代替Arraylist和hashmap,比如CopyOnWriteArrayList(COW)写时复制容器,在读写时是线程安全的,该容器在add,remove等操作时,并不是在原数组上修改,而是在原数组上拷贝一份,在新数组上修改,待完成后才将旧数组的引用指向新数组。所以CopyOnWrite容器只能保证数据的最终一致性,并不能保证数据的实时一致性八.实现数组拷贝的方法有哪些?速度怎么样?
(1)从速度上看:System.arraycopy > clone > Arrays.copyOf > for
(2)for速度慢是因为每次都要从起点开始寻找指定下标,并且每次循环都要判断是否达到数组最大长度(3)system.arrayCopy()是一个native方法,(本地方法,即c/c++已经编译成机器码的方法)九.java中,一个二维数组是怎样分配内存空间的?
事实上,java中只有一维数组,二维数组其实就是一个存放了数组的数组,创建一个二维数组时,一个数组对象所占的空间在堆上被分配,然后这个数组中的每一个元素空间又有一个引用指向另一个数组,这样就构成了一个二维数组