文章目录
- 1:Java 容器有那些 ?
- 2:Collection 和 Collections有什么区别 ?
- 3:List,Set,Map 之间的区别是什么 ?
- 4:HashMap 和 HashTable 区别 ?
- 5:HashMap ,HashTable,TreeMap ,ConcurrentHashMap 各自特点 ?
- 6:HashSet 底层实现原理 ?
- 7:ArrayList 和 LinkedList 的区别是什么 ?
- 8:如何实现数组和 List 之间的转换?
- 9:ArrayList 和 Vector 的区别是什么?
- 10:在 Queue 中 poll()和 remove()有什么区别?
- 11:那些集合类是线程安全的?那些是不安全的?
- 12:迭代器 Iterator 是什么,使用,以及特点?
- 13:怎么确保一个集合不能被修改?
- 14:代码地址
1:Java 容器有那些 ?
Java 容器分为Collection 和 Map 两大类 ,其下又有很多子类,如下所示 :
- Collection----接口
- List----接口
- ArrayList
- LinkedList
- Vector
- Set----接口
- HashSet----底层实现为HashMap
- LinkedHashSet
- List----接口
- Map----接口
- HashMap
- LinkedHashMap----继承HashMap
- TreeMap
- ConcurrentHashMap
- Hashtable
- HashMap
2:Collection 和 Collections有什么区别 ?
- Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等
- Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法:Collections. sort(list)
3:List,Set,Map 之间的区别是什么 ?
- 主要区别在于两个方面 : 元素是否排序,是否允许元素重复
- 排序: List 不排序 ; HashSet 可排序; HashMap 可排序(按照 key 排序)
- 元素重复: List 不去重 ; HashSet 去重; HashMap 去重(key 不能重复),value 可重复。
- 总结: List 即不排序,也不去重 ; HashSet ,HashMap,即去重也排序,只不过 HashMap 是针对 key 值来说的
- 代码如下
/**
* 测试 是否排序
* <p>
* 运行结果:
* ArrayList = [a, c, b]
* HashSet = [a, b, c]
* HashMap = {a=1, b=2, c=3}
*/
void show1() {
System.out.println("-------------------测试是否排序---------------------");
List arrayList = new ArrayList();
Set hashSet = new HashSet();
Map hashMap = new HashMap();
arrayList.add("a");
arrayList.add("c");
arrayList.add("b");
System.out.println("ArrayList = " + arrayList);
hashSet.add("a");
hashSet.add("c");
hashSet.add("b");
System.out.println("HashSet = " + hashSet);
hashMap.put("a", "1");
hashMap.put("c", "3");
hashMap.put("b", "2");
System.out.println("HashMap = " + hashMap);
}
4:HashMap 和 HashTable 区别 ?
-
从代码架构上说:
- HashMap继承自 AbstractMap 。
- 而 HashTable继承自Dictionary类。
- 不过都实现了 Map,Cloneable(可复制),Serializable(可序列化) 这三个接口。
-
从功能方面说:
- HashMap 中的 key-value 支持 key-value , null-null , key-null, null-value 四种形式。
- 而HashTable 只支持 key-value 这一种形式。
- 总结: 当判断HashMap 中某个key是否存在时,不能使用 get()
方法取判断,因为当你的key=null时,返回的也是null,所以应该使用containsKey() 方法去判断。
-
从线程安全说:
- HashMap : 非线程安全(没有被synchronized) 。
- HashTable : 线程安全(方法几乎被synchronized修饰)
- 但是如果需要HashMap 是线程安全是怎么处理呢?
- 可以使用 Collections.synchronizedMap(Map)
- 也可以使用ConcurrentHashMap,它比HashTable 效率高好多倍,因为该类使用的是分段锁,并不对整个数据进行锁定。
-
从容量初始化说:
- HashMap 默认初始化 = 16 ,之后每次扩容为原来的 2 倍 。
- HashTable 默认初始化 = 11 ,之后每次扩容为原来的 2n+1。
- 计算hash值不一样:
- HashMap : 为了得到元素的位置,首先需要根据元素的key计算出一个 hash 值,然后再用这个 hash 值来计算得到最终位置。
- HashTable: 直接使用对象的 hashCode,hashCode 是 JDK 根据对象的地址或者字符串或者数字计算出来的 int 类型的数值,然后再使用保留余数获取最终的位置。
-
总结: 对于HashMap 和 HashTable 的使用,应尽量使用HashMap,因为无论是否需要线程安全(需要线程安全时可以使用上面两种方式保持),HashMap都要 比 HashTable 效率高。
5:HashMap ,HashTable,TreeMap ,ConcurrentHashMap 各自特点 ?
- 相同点:都是 Map 接口的实现类 ; 因此都 有 put(key,value),get(key) 的操作
- 不同点:
- HashMap :
- 支持 key-value , null-null , key-null, null-value 四种形式。
- 线程不安全。
- 默认初始容量为16(1<<4)扩容方式为原来的2倍 。
- 底层数据结构 : jdk1.8(数组 + 链表,当链表长度超过8时,链表转换为红黑树) 。
- ConcurrentHashMap:
- 只支持 key-value ((key == null || value == null) , 将抛出NullPinterException)
- 线程安全 (分段锁)
- 数组+链表+红黑树
- HashTable:
- 只支持 key-value
- 线程安全
- 数组+链表
- TreeMap:
- 只支持key-value 形式
- 线程非安全
- 红黑二叉树
- HashMap :
6:HashSet 底层实现原理 ?
- HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。
- 总结: HashSet 实现了Set相关接口,但是底层使用的HashMap来做事的,所以才会带个hash的名字。
7:ArrayList 和 LinkedList 的区别是什么 ?
- 数据结构: ArrayList : 动态数组;LinkedList : 双向链表。
- 总结:因此在频繁读取数据时用ArrayList; 在写数据时用LinkedList。
8:如何实现数组和 List 之间的转换?
- 数组转 List:使用 Arrays. asList(array) 进行转换。
- List 转数组:使用 List 自带的 toArray() 方法。
9:ArrayList 和 Vector 的区别是什么?
- ArrayList
- 线程安全:非线程安全
- 性能:> Vector
- 扩容:根据实际的需要动态的调整容量,增加 50%。
- Vector
- 线程安全:线程安全
- 性能:< ArrayList
- 扩容:根据实际的需要动态的调整容量,Vector 扩容每次会增加 1 倍。
10:在 Queue 中 poll()和 remove()有什么区别?
- 相同点:都是返回第一个元素,并在队列中删除返回的对象。
- 不同点:如果没有元素 remove()会直接抛出NoSuchElementException 异常,而 poll()会返回 null。
- 代码示例:
Queue<String> queue = new LinkedList<String>();
queue. offer("string"); // add
System. out. println(queue. poll());
System. out. println(queue. remove());
System. out. println(queue. size());
11:那些集合类是线程安全的?那些是不安全的?
- 线程安全:
- List
- Vector
- Map
- Hashtable
- ConcurrentHashMap
- Stack
- List
- 非线程安全:
- List
- ArrayList
- LinkedList
- Set
- HashSet
- LinedHashSet
- Map
- HashMap
- TreeMap
- List
12:迭代器 Iterator 是什么,使用,以及特点?
- Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
- 特点:Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
- 使用
/**
* @return void
* @Author ZQ
* @Description 输出:
* 张三
* 李四
* 王五
* <p>
* 特点:在两个线程同时操作该list的时可以保证线程安全
* @Date 2020/2/6 13:46
* @Param [args]
**/
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
}
13:怎么确保一个集合不能被修改?
- 可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。
- 代码如下:
/**
* @return void
* @Author ZQ
* @Description 报错信息: UnsupportedOperationException
* @Date 2020/2/6 13:54
* @Param [args]
**/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("xfj");
Collection<String> clist = Collections.unmodifiableCollection(list);
clist.add("zq");//运行到这报错,因为已经加载成不可被修改了,可以使用clist集合来进行只读的操作。
System.out.println(list.size());
}