Java中的集合概述

Posted 奔跑在梦想的道路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的集合概述相关的知识,希望对你有一定的参考价值。

Java中的集合类有两个重要的分支,分别是接口Collection(包括List,Set等)和接口Map。

由于HashSet的内部实现原理使用了HashMap,所以我们先来了解Map集合类。

1.HashMap、Hashtable和TreeMap

(1)java.lang.Object

继承者 java.util.AbstractMap<K,V>

继承者 java.util.HashMap<K,V>

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

(2)java.lang.Object

继承者 java.util.Dictionary<K,V>

继承者 java.util.Hashtable<K,V>

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable

(3)java.lang.Object

继承者 java.util.AbstractMap<K,V>

继承者 java.util.TreeMap<K,V>

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable

其中,HashMap不是线程
安全的;HashTable是线程安全的,其线程安全是通过sychronize实现的。基于该原因,HashMap效率高于HashTable。

HashMap的键可以为null,HashTable不可以。

在多线程环境下,HashMap配合Collections工具类使用来实现线程安全;还可以选择ConcurrentHashMap,该类的线程安全是通过Lock的方式实现的,所以效率高于Hashtable。

数组,链表,哈希表,三者各有优劣。数组使用连续的内存空间,查找速度快,增删慢;链表充分利用了内存,存储空间是不连续的,首尾各存储上下一个节点的信息,所以寻址较慢,即查找速度慢,但是增删快;哈希表综合了前二者的优点,一个哈希表,由数组和链表组成。假设一条链表有1000个节点,现在要查找最后一个节点,就得从第一个遍历到最后一个;如果用哈希表,将这条链表分为10组,用一个容量为10的数组来存储这10组链表的头结点(a[0] = 0 , a[1] = 100 , a[2] = 200 …以此类推),这样的话就明显提高了寻址效率。

HashMap就是基于上述哈希表原理实现的寻址,Hashtable同理,只不过做了同步处理。

HashMap输出是无序的,这个无序不是说每次遍历的结果顺序不一样,而是说与插入顺序不一样

另外,TreeMap是按键排序的,默认升序,所以可以通过TreeMap来实现。TreeMap的排序是在底层基于比较器(Comparator接口的int compare(T o1,T o2),Comaparable接口的int compareTo(T o))实现的。

HashMap实现线程同步的方式有两种,一种是:

       Map<Integer , String> hs = new HashMap<Integer , String>();

        hs = Collections.synchronizedMap(hs);        

  另一种是:

    ConcurrentHashMap<Integer , String> hs = new ConcurrentHashMap<Integer , String>();

  2.List接口及其子类ArrayList,LinkedList,Vector,Stack。

public interface List<E> extends Collection<E>

(1)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.ArrayList<E>

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

(2)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.AbstractSequentialList<E>

继承者 java.util.LinkedList<E>

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable

(3)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.Vector<E>

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

(4)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractList<E>

继承者 java.util.Vector<E>

继承者 java.util.Stack<E>

public class Stack<E> extends Vector<E>

其中,ArrayList和Vector本质都是用数组实现的,而LinkList是用双链表实现的。所以,Arraylist和Vector在查找效率上比较高,增删效率比较低;LinkedList则正好相反。

ArrayList是线程不安全的,Vector是线程安全的,在效率没有ArrayList高。实际使用中,一般也不怎么用Vector,可以自己做线程同步,也可以用Collections配合ArrayList实现线程同步。

在排序上,List是使用Collections类的sort方法,构造Comparator或者让List中的对象实现Comparable都可以。

Stack继承自Vector,在用法、线程安全方面的跟Vector都差不多,有几个地方需要注意,一是add()和push(),stack是将最后一个element作为栈顶的,add()返回boolean,就是添加成功了没有,push()返回的是添加的元素,一般推荐使用push;二是peek()和pop(),这两个方法都能得到栈顶元素,区别是peek()只是读取,对原栈没有什么影响,pop()从字面上就能理解为“出栈”,所以原栈的栈顶元素就没了。

3.Set接口及其子类HashSet,TreeSet。

public interface Set<E> extends Collection<E>

(1)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractSet<E>

继承者 java.util.HashSet<E>

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable

(2)java.lang.Object

继承者 java.util.AbstractCollection<E>

继承者 java.util.AbstractSet<E>

继承者 java.util.TreeSet<E>

public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable

总的来说,Set集合类的特点是可以去重,它们的内部实现都是基于Map的,用的是Map的key,而Map的key是不可以重复的。既然要去重,就需要比较,而比较是基于hascode()方法和equals()方法的。


以上是关于Java中的集合概述的主要内容,如果未能解决你的问题,请参考以下文章

Java集合:概述

Java中的集合(List,Set,Map)(知识点详解)(看完这篇就够了)

Java集合之Collection概述

COREJAVA概述-集合

COREJAVA概述-集合

COREJAVA概述-集合