1.集合有哪些?
Collection接口和Map接口是所有集合框架的父接口:
-
Collection接口的子接口包括:Set接口和List接口
(1) List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等;
(2) Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等;
-
Map接口的实现类主要有:
HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
2.List、Set、Map 的区别?
3.数组和 list 之间的转换?
-
List转换成为数组:调用ArrayList的 toArray 方法。
-
数组转换成为List:调用Arrays的 asList 方法。
4.ArrayList扩容机制
ArrayList集合大小如果创建时没有指定,则默认为0,若已经指定集合大小,则初始值为指;
当第一次添加数据的时候,集合大小扩容为10,
第二次及其后续每次按照
int oldCapacity = elementData.length;
newCapacity = oldCapacity+(oldCapacity>>1)
5.ArrayList 、Vector和LinkedList 的区别?
-
ArrayList:底层基于数组,线程不安全,查询和修改效率高,但是增加和删除效率低,如果需要大量的查询和修改则可以选择ArrayList;
-
LinkedList:底层双向链表结构,线程不安全,查询和修改效率低,但是增加和删除效率高,如果需要大量的添加和删除则可以选择LinkedList;
-
Vector:如果创建Vector时没有指定容量,则默认容量为10,底层基于数组实现,线程是安全的,底层 采用synchronized同步方法进行加锁,很少用
6.Array 和 ArrayList 有何区别?
-
Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
-
Array是指定大小后不可变的,而ArrayList大小是可变的。
-
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
7.在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
8.如果要保证ArraList线程安全,有几种方式?
-
自己重写一个ArrayList集合类,根据业务一般来说,add/set/remove加锁
-
采用synchronized加锁:
List<Object> list = Collections.synchronizedList(new ArrayList<>());
-
采用 ReentrantLock加锁:
new CopyOnWriteArrayList<>().add("");
9.HashMap与HashTable的区别?
-
HashMap继承自AbstractMap类;而Hashtable继承自Dictionary类;
-
HashMap允许K/V都为null;后者K/V都不允许为null;
-
HashMap没有考虑同步,是线程不安全的,效率上比hashTable要高;Hashtable使用了synchronized关键字,是线程安全的;
-
hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
-
默认初始大小和扩容方式不同。HashMap 默认初始大小 16,容量必须是 2 的整数次幂,扩容时将容量变为原来的2倍;Hashtable 默认初始大小 11,扩容时将容量变为原来的 2 倍加 1。
-
迭代器不同。HashMap 的 Iterator 是 fail-fast 迭代器;Hashtable 还使用了 enumerator 迭代器。
10.HashSet 的实现原理?
-
HashSet底层由HashMap实现
-
HashSet的值存放于HashMap的key上
-
HashMap的value统一为PRESENT
11.hashmap的底层原理,会不会产生哈希冲突?
12.HashMap遍历?
两种方式遍历:使用EntrySet
遍历;使用KeySet
遍历
13.Set 遍历方法?
-
迭代遍历:
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
-
for循环遍历:
for (String str : set) {
System.out.println(str);
}
14.HashSet和TreeSet的区别?
HashSet的存储方式:哈希码算法,加入的对象需要实现hashcode()方法,快速查找元素 TreeSet的存储方式:按序存放,想要有序就要实现Comparable接口
不同点:
(1)HashSet由哈希表(实际上是一个HashMap实例)支持,不保证set的迭代顺序,并允许使用null元素。
(2)基于HashMap实现,API也是对HashMap的行为进行了封装,可参考HashMap
15.底层数据结构
-
Vector底层是数组。
-
Stack底层是Vector。
-
HashTable底层是链地址法组成的哈希表(即数组+单项链表组成)。
-
ArrayList底层是数组。
-
LinkedList底层是双向链表。
-
HashMap底层与HashTable原理相同,Java 8版本以后如果同一位置哈希冲突大于8则链表变成红黑树。
-
LinkedHashMap底层修改自HashMap,包含一个维护插入顺序的双向链表。
-
TreeMap底层是红黑树。
-
HashSet底层是HashMap。
-
LinkedHashSet底层是LinkedHashMap。
-
TreeSet底层是TreeMap。
16.迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
17.Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
-
使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素;
注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
-
使用next()获得序列中的下一个元素;
-
使用hasNext()检查序列中是否还有元素;
-
使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
18.Iterator 和 ListIterator 有什么区别?
-
Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
-
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
-
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
19.怎么确保一个集合不能被修改?
使用 JDK中java.util.Collections 类,unmodifiable*** 方法赋值原集合。
当再修改集合时,会报错 java.lang.UnsupportedOperationException。从而确保自己定义的集合不被其他人修改。
public class TestCollectionUnmodify {
static List<String> list = new ArrayList<String>();
static Set<String> set = new HashSet<String>();
static Map<String, String> map = new HashMap<String, String>();
static {
list.add("1");
list.add("2");
list.add("3");
set.add("1");
set.add("2");
set.add("3");
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
}
public static void main(String[] args) {
list = Collections.unmodifiableList(list);
set = Collections.unmodifiableSet(set);
map = Collections.unmodifiableMap(map);
listModify();
setModify();
mapModify();
}
public static void listModify() {
list.add("4");
}
public static void setModify() {
set.add("4");
}
public static void mapModify() {
map.put("3", "4");
}
}