java中三大集合类Map,Set,List的详细介绍

在讲Map,Set,List三大接口之前,我们先来了解下Set和List的父类接口Collection接口
 
一:Collection接口:是java.util包下的一个接口:
其中有一些主要的方法:
size();
isEmpty();
clear();
contains( );
add();
remove();
这几个方法都比较常见,在这就不详细介绍啦!!
还有一个特殊的方法,因为Collection接口扩展了Iteratable接口,所有实现Itreable接口的集合必须提供一个称为iterator()的方法,所以Collection还有iterator()方法,用法如下
Iterator it=set/list.iterator();
while(it.hasNext( )){
AnyType item=it.next( );
System.out.println(item);
}
这里的set\list是List或者Set接口的实例,有上可见,此方法主要是用于遍历的。
附:Collectionsjava.util包下的类,包含各种有关集合操作的静态方法,可以理解成对继承Collection的接口都有效。

Collections类中的常用方法:

(1)Collections.sort(list):给队列list中的对象排序

(2)Collection.max(list):取队列中最大的对象;Collection.min(list):取队列中最小的对象

(3)Collection.copy(list1,list2):如果list1.length>list2.length,那么list1的前list2.length部分会被覆盖;否则IndexOutOfBoundsException报错。

List2list1的子列表:

(4)Collections.indexOfSubList(list, list2)第一次出现的位置

(5)Collections.lastIndexOfSubList(list, list2);最后一次出现的位置

二:

继承Collection接口的有List和Set接口:

List:ArrayList和LinkedList

Set:TreeSet和HashSet

  1. <</span>span style="font-family:Microsoft YaHei;font-size:12px;">世间上本来没有集合,(只有数组参考C语言)但有人想要,所以有了集合  
  2. 有人想有可以自动扩展的数组,所以有了List  
  3. 有的人想有没有重复的数组,所以有了set  
  4. 有人想有自动排序的组数,所以有了TreeSet,TreeList,Tree**  
  5.   
  6. 而几乎有有的集合都是基于数组来实现的.  
  7. 因为集合是对数组做的封装,所以,数组永远比任何一个集合要快  
  8.   
  9. 但任何一个集合,比数组提供的功能要多  
  10.   
  11. 一:数组声明了它容纳的元素的类型,而集合不声明。这是由于集合以object形式来存储它们的元素。  
  12.   
  13. 二:一个数组实例具有固定的大小,不能伸缩。集合则可根据需要动态改变大小。  
  14.   
  15. 三:数组是一种可读/可写数据结构---没有办法创建一个只读数组。然而可以使用集合提供的ReadOnly方法,以只读方式来使用集合。该方法将返回一个集合的只读版本。</</span>span>  
  • ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。 
  • LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。

 

 

ArrayList() 和LinkedList()的详细介绍与区别:

由于ArrayList()的底层是数组实现的,因此查询是基于索引的,查询速度快,但是增加、删除元素慢,原因是每增加、删除一个元素的话,整个整体元素都要重新移动位置(当然增加、删除的位置在最后那个位置除外

由于LinkedList(): 在实现中采用链表数据结构,因此查询速度较慢,因为每次查询都要从头开始一个一个的找,但是增加、删除元素的速度较快

ArrayList使用一个内置的数组来存储元素,这个数组的起始容量是10.当数组需要增长时,新的容量按如下公式获得:新容量=(旧容量*3)/2+1,也就是说每一次容量大概会增长50%。这就意味着,如果你有一个包含大量元素的ArrayList对象,那么最终将有很大的空间会被浪费掉,这个浪费是由ArrayList的工作方式本身造成的。如果没有足够的空间来存放新的元素,数组将不得不被重新进行分配以便能够增加新的元素。对数组进行重新分配,将会导致性能急剧下降。如果我们知道一个ArrayList将会有多少个元素,我们可以通过构造方法来指定容量。我们还可以通过trimToSize方法在ArrayList分配完毕之后去掉浪费掉的空间。

 

 

ArrayList() 、LinkedList()和vector的区别:

Vector的api描述是:从jdk 1.2版本开始,该类被修正为实现List接口,并成为Java Collection集合框架的一员,区别于其他一些新的集合实现类,Vector是线程安全的。

ArrayList() 、LinkedList()是线程不安全的。

解决ArrayListLinkedList线程不安全这个问题通常有两种方法(个人认为)

一:使用synchronized关键字,这个大家应该都很熟悉了,不解释了;

二:使用Collections.synchronizedList();使用方法如下:

        假如你创建的代码如下:List> data=new ArrayList>();

        那么为了解决这个线程安全问题你可以这么使用Collections.synchronizedList(),如:

        List> data=Collections.synchronizedList(new ArrayList>());

  • HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快 
  • TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。 TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。 
  • LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

 

Set接口

Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

 

HashSet
HashSet有以下特点
 不能保证元素的排列顺序,顺序有可能发生变化
 不是同步的
 集合元素可以是null,但只能放入一个null
当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。

其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

 

LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

 

TreeSet类
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
TreeSet
判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0

List和Set的区别:

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。

Set的功能方法 

Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责) 

Set : 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。

List的特征是其元素以线性方式存储,集合中可以存放重复对象。 次序是List最重要的特点:它保证维护元素特定的顺序

注:Set对象不按特定的方式排序,而List它保证维护元素特定的顺序最直接的证明是:往ArrayList对象和HashSet对象中添加相同顺序的对象元素,不做任何排序处理,然后遍历输出,你会发现List的输出顺序呢是和输入顺序是一致的,而Set的输出顺序是不一致的。


 

Map:

HashMap

HashTable

TreeMap

HashMap和HashTable的区别:

我们先看2个类的定义

[java] view plain copy

1. public class Hashtable  

2.     extends Dictionary  

3.     implements Map, Cloneable, java.io.Serializable  

[java] view plain copy

1. public class HashMap  

2.     extends AbstractMap  

3.     implements Map, Cloneable, Serializable  

AbstractMap接口的直接子类:HashMapTreeMap

Hashtable

注意1 方法是同步的
注意2 方法不允许value==null
注意3 方法调用了keyhashCode方法,如果key==null,会抛出空指针异常 

HashMap

注意1 方法是非同步的
注意2 最多只能允许一条记录的键为null,允许多条记录的值为null

注意3 方法并没有对value进行任何调用,所以允许为null

HashMapHashtablecontains方法去掉了,改成containsvaluecontainsKey。因为contains方法容易让人引起误解

2. HashTableHashMap区别

第一,继承不同。

public class Hashtable extends Dictionary implements Map
public class HashMap  extends AbstractMap implements Map

第二

Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

第三

Hashtable中,keyvalue都不允许出现null值。

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

第四,两个遍历方式的内部实现上不同。

HashtableHashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式。

HashMap的遍历:

第一种:
  Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }
  效率高,以后一定要使用此种方式!
第二种:
  Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }
 第三种:(实际上也是第二种)

 Map map=new HashMap();

for(Integer key:map.keySet()){

System.out.println(key+" "+map.get(key));

}

第五

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

第六

HashtableHashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTablehash数组默认大小是11,增加的方式是 old*2+1HashMaphash数组的默认大小是16,而且一定是2的指数。 


 

 

TreeSetTreeMap的区别:


TreeMap  TreeSet  Java Collection Framework 的两个重要成员,其中 TreeMap  Map 接口的常用实现类,而 TreeSet  Set 接口的常用实现类。虽然 TreeMap  TreeSet 实现的接口规范不同,但 TreeSet 底层是通过 TreeMap 来实现的(如同HashSet底层是是通过HashMap来实现的一样),因此二者的实现方式完全一样。而 TreeMap 的实现就是红黑树算法。

HashSet完全类似,TreeSet里面绝大部分方法都市直接调用TreeMap方法来实现的

相同点:

TreeMapTreeSet都是有序的集合,也就是说他们存储的值都是拍好序的。

TreeMapTreeSet都是非同步集合,因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步

运行速度都要比Hash集合慢,他们内部对元素的操作时间复杂度为O(logN),而HashMap/HashSet则为O(1)

不同点:

最主要的区别就是TreeSetTreeMap非别实现SetMap接口

 

TreeSet只存储一个对象,而TreeMap存储两个对象KeyValue(仅仅key对象有序)

TreeSet中不能有重复对象,而TreeMap中可以存在

文章参考了一下几位的博客,如有侵权,请联系删除:

http://baike.xsoftlab.net/view/250.html

http://blog.csdn.net/speedme/article/details/22398395

http://blog.csdn.net/speedme/article/details/18743445

http://blog.csdn.net/speedme/article/details/22661671

猜你喜欢

转载自blog.csdn.net/qq_27028821/article/details/52262690