Java 集合分析总结


面试图灵机器人的过程中被问到HashMap, Hashtable 和 TreeMap的区别,居然被问住了,虽然工作四年了,在解决具体问题时貌似还没遇到过翻不过去的坑。但是最近的面试也深刻的认识到基础知识该忘的忘,该不知道的不知道,究其原因,都是之前懒得或不屑总结。

就这个问题本身,回来学习后回答如下:

从两个方面分析

一,是否可以使用null,作为key或者value

HashMap,可以使用null值作为key或者value,当null作为key时,由于HashMap的key,不可重复,所以最多可以存入一个key为null的Entry。而当null作为value时,可以有多个value为null的Entry。

Hashtable,不可以将null值作为key或value,当向Hashtable中放入null值时,会报NullPointExecption。

以上两种,在内部实现时,均依靠key值使用Hash原理进行元素存储。他们均是Map接口的典型实现类。

TreeMap,是SortedMap接口的实现类,而SortedMap继承自Map接口。TreeMap内部维护以Key为排序依据的红黑树数据结构,当null作为key时,会NullPointException,但是当null用作value时可以有多个value为null的Entry。

验证代码如下:

import java.util.HashMap;
import java.util.Hashtable;
import java.util.TreeMap;

public class MapNullTest {

    public static void main(String[] args) {
        //1. HashMap null test
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put(null, null);
        hashMap.put(null, null);
        hashMap.put("a", null);
        hashMap.put("b", null);
        System.out.println("hashMap: " + hashMap);
       
        //2. HashTable null test
        Hashtable<String, String> hashTable = new Hashtable();
        try {
            hashTable.put(null, "a");   
        } catch (NullPointerException e) {
            System.out.println("hashTable put (null, a) NullPointerException");
        }
       
        try {
            hashTable.put("a", null);
        } catch (Exception e) {
            System.out.println("hashTable put (a, null) NullPointerException");
        }
        System.out.println("hashTable: " + hashTable);
       
        //3. TreeMap null test
        TreeMap<String, String> treeMap = new TreeMap<>();
        try {
            treeMap.put(null, "a");   
        } catch (NullPointerException e) {
            System.out.println("treeMap put (null, a) NullPointException");
        }
       
        treeMap.put("a", null);
        treeMap.put("b", null);
        System.out.println("treeMap: " + treeMap);
    }

}

执行结果如下:

hashMap: {null=null, a=null, b=null}
hashTable put (null, a) NullPointerException
hashTable put (a, null) NullPointerException
hashTable: {}
treeMap put (null, a) NullPointException
treeMap: {a=null, b=null}

二、是否是线程安全的

HashMap 和 TreeMap均不是线程安全的,如需要线程安全时,可使用Collections的synchronizedXxx()方法获取到对应的线程安全对象。

Hashtable 是线程安全的。

Java 集合总结

java 集合类主要由两个接口派生而出,Collection 和 Map接口。

一、Collection 族

其子接口有,Set,Queue和List接口。

1、Set 无序集合,集合中元素不可重复,常用Set类。

HashSet 元素的排列无序,不是线程同步的,集合中的元素可以为null,但是只可以有一个,其中的元素,因为不可以重复,所以需要判断两个对象是否相等,判断标准为两个对象通过equals()判断为true,且hashCode()方法返回值也相等。LinkedHashSet是其子类,它依然是一个HashSet,但内部使用链表记录了元素的添加顺序,所以其中元素的顺序与添加顺序是一致的。

TreeSet 内部使用红黑树来存储集合元素,加入TreeSet中的元素需要实现Comparable接口,因为TreeSet需要调用compareTo方法对元素进行比较从而排序,所以TreeSet中的元素顺序,不是插入顺序,而是compareTo的比较顺序。TreeSet判断两个对象是否相等的唯一标准就是compareTo返回值是否为0。若内部元素未实现Comparable接口,则需要在创建TreeSet对象时为其指名排序规则,以一个Comparator对象与集合关联,以指名排序规则。

EnumSet 专门为Enum对象设计的Set。

2、List 代表一个有序可重复的集合,且每一个元素都有对应的索引。

ArrayList 典型的List 实现类。

3、Queue 模拟队列的数据结构

PriorityQueue 标准的对列实现类,不过其队列中元素的排序并非按照入队顺序排列,而是依照元素实现的Comparable接口或者与集合绑定的Comparator对象定义的标准进行排列的,在出队时按照元素的排列顺序进行出队。

Deque 是Queue的子接口。

ArrayDeque是 Deque的典型实现类,实现双向队列,也可用作Stack来使用。

LinkedList 实现了List接口同时也实现了Deque接口,所以它是一个功能强大的结合,即可作为List使用,也可作为双向队列或栈来使用。

二、Map族

参照面试问题的回答,另外就是有几个重要的实现类:

WeakHashMap,保留对Key所引用对象的弱引用,可在key所引用的对象没有其它引用时,自动删除该key-value,以保证该元素的释放。

Properties,封装了对属性文件的读写,可以方便的将key-value的属性文件读入Properties对象中,也可方便的将Properties对象方便的存入属性文件中。

本文永久更新链接地址

相关内容