List、Set、Map的区别和关系
扩展链接.
List、Set是实现了Collection接口的子接口;而Map是另一个集合接口;(Collection接口和Map接口是平级的)
三者之间的区别如下:
元素重复性:
① List允许有重复的元素。任何数量的重复元素都可以在不影响现有重复元素的值及其索引的情况下插入到List集合中;
② Set集合不允许元素重复。Set以及所有实现了Set接口的类都不允许重复值的插入,若多次插入同一个元素时,在该集合中只显示一个;
③ Map以键值对的形式对元素进行存储。Map不允许有重复键,但允许有不同键对应的重复的值;
元素的有序性:
① List及其所有实现类保持了每个元素的插入顺序;
② Set中的元素都是无序的;但是某些Set的实现类以某种殊形式对其中的元素进行排序,如: LinkedHashSet按照元素的插入顺序进行排序;
③ Map跟Set一样对元素进行无序存储,但其某些实现类对元素进行了排序。如:TreeMap根据键对其中的元素进行升序排序;
元素是否为空值:
① List允许任意数量的空值;
② Set最多允许一个空值的出现;[ 当向Set集合中添加多个null值时,在该Set集合中只会显示一个null元素]
③ Map只允许出现一个空键,但允许出现任意数量的空值;
总结:
List中的元素,有序、可重复、可为空;
Set中的元素,无序、不重复、只有一个空元素;
Map中的元素,无序、键不重,值可重、可一个空键、多可空值;
实现类:
① List:ArrayList、LinkedList;
② Set:HashSet、LinkedHashSet、TreeSet、SortedSet等等;
③ Map:HashMap、TreeMap、WeakHashMap、LinkedHashMap、IdentityHashMap等等;
List集合的子类ArrayList、Vector、LinkedList之间的区别:
ArrayList和Vector都是以数组的方式存储数据的,此数组长度大于实际存储元素个数,以方便插入元素;它们都允许直接按索引获取元素;由于在插入数据时,涉及到数组元素的移动等内存操作,所以在插入数据时执行速度较慢;Vector是线程安全的(synchronized),所以性能上要比ArrayList差;
而LinkedList是以双向链表的形式存储数据的,在按索引获取数据时只需要向前或者向后进行遍历即可;在插入数据时,只需要记录本项的前后项即可,所以插入速度较快。
HashMap和HashTable的区别:
HashMap是HashTable的轻量级实现(非线程安全的实现),它们都实现了Map接口,主要区别在于
HashMap允许空(null)键值(key),由于非线程安全,效率上高于HashTable。
HashMap允许将null作为一个entry的key或者value,而HashTable不允许。
HashMap去掉了HashTable的contains方法,改成containsValue和containsKey方法。
二者最大的不同是,HashTable的方法是synchronized(线程安全的),而HashMap不是,在多个线程访问HashTable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。
基础知识
List
List是一个接口,继承自Controller接口
List特点:元素有序,可重复
ArrayList,LinkedList与List的区别:
1.List是接口类,ArrayList,LinkedList是List的实现类。
2.ArrayList是动态数组(顺序表)的数据结构,顺序表的存储地址是连续的,所以查找速度比较快,但是在插 入和删除时,由于需要把其他的元素顺序向后移动(或向前移动),所以会比较耗时。
Vector也是动态数组结构,但是是线程同步的。
3.LinkedList是链表的数据结构。链表的存储地址是不连续的,每个存储地址通过指针指向,在查找时需要进行通过指针遍历元素,所以在查找时会比较慢。由于链表插入时不需要移动其他元素,所以插入和删 除时会比较快。
List的基本方法:
List list = New ArrayList();
list.add(“java”); //向集合追加元素
list.add(2,“hadoop”); //向集合插入元素
System.out.println(list.get(2)); //根据下标取出元素
System.out.println(list.size()); //集合中元素的个数
list.remove(2); //根据下标删除某一个元素
List.contains(“java”); //true看集合中是否包含某一个对象,使用equals比较
List.contains(new String(“ibm”)); //true看集合中是否包含某一个对象,使用equals比较
equals与== 的区别
1.是比较对象的地址值,即判断是否是同一个对象
2.equals可以重写,比较内容是否相同
3.equals在Object中,比较的是是否为同一对象,与相同
HashMap
HashMap存储的是键值对;可以接受null键值和值,而HashTable则不能;HashMAp是非Synchronized;
HashMap工作原理:hashMap是基于hashing的原理,我们使用put(key,value)存储对象到hashmap中,使用get(key)从HashMap中获取对象。
当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象.HashMap是在bucket中储存键对象和值对象,作为Map.Entry。
问题1:当两个对象的hashcode相同会发生什么?
因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用LinkedList存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在LinkedList中。
问题二:如果两个键的hashcode相同,你如何获取值对象?
因为多线程会导致HashMap的Node链表形成环形数据结构,一旦形成环形数据结构,Node的next节点永远不为空,就会在获取Node时产生死循环。
问题三:Map的排序问题
TreeMap默认升序,可以用Comparator的compare方法进行排序
如果需要对值进行排序,需要Collections的sort的compare方法进行排序
保证线程安全:
1、HashTable源码中是使用synchronized来保证线程安全的。
2、ConcurrentHashMap,在8中CHM摒弃了Segment(包含一个segment数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术)的概念,而是启用了一种全新的方式实现,利用CAS算法。
3、SynchronizedMap也是使用synchronized来保证线程安全的。