java 集合整理

来源:互联网 发布:windows loader 编辑:程序博客网 时间:2024/06/06 16:02

Map

HashMap

TreeMap

HashTable

LinkedHashMap

 

1.Map

存储元素对(键值集合)

1Map有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap

2)哈希映射技术:

哈希映射是将元素映射到数组的非常简单的机制

哈希映射结构由一个存储元素的内部数组组成。由于内部采用数组存储,因此必然存在一个用于确定任意键访问数组的索引机制。实际上,该机制需要提供一个小于数组大小的整数索引值。该机制称作哈希函数。在 Java 基于哈希的 Map 中,哈希函数将对象转换为一个适合内部数组的整数。您不必为寻找一个易于使用的哈希函数而大伤脑筋: 每个对象都包含一个返回整数值的 hashCode() 方法。要将该值映射到数组,只需将其转换为一个正值,然后在将该值除以数组大小后取余数即可。

(3)方法

get(),put(),putAll(),containsKey,containsValue,isEmpty(),size(),

equals(),hashcode(),clear(),remove(),

entryset(),keyset(),values()

(4)优化hashmap

     调整map实现大小

 在哈希术语中,内部数组中的每个位置称作“存储桶”(bucket),而可用的存储桶数(即内部数组的大小)称作容量 (capacity)。为使 Map 对象有效地处理任意数目的项,Map 实现可以调整自身的大小。但调整大小的开销很大。调整大小需要将所有元素重新插入到新数组中,这是因为不同的数组大小意味着对象现在映射到不同的索引值。先前冲突的键可能不再冲突,而先前不冲突的其他键现在可能冲突。这显然表明,如果将 Map 调整得足够大,则可以减少甚至不再需要重新调整大小,这很有可能显著提高速度。

使用负载因子

为确定何时调整大小,而不是对每个存储桶中的链接列表的深度进行记数,基于哈希的 Map 使用一个额外参数并粗略计算存储桶的密度。

Map 在调整大小之前,使用名为“负载因子”的参数指示 Map 将承担的“负载”量,即它的负载程度。负载因子、项数(Map 大小)与容量之间的关系简单明了:

 如果(负载因子)x(容量)>(Map 大小),则调整 Map 大小

(5)集合视图

集合视图对象可以说是具有限制的集合对象

视图对象,具有访问数组元素set,get的方法。但是如果调用改变数组的方法就会抛出异常.

 

Map接口在Java集合中提供三个集合视图:
1)Set keyset():返回map中包含的所有key的一个Set视图。集合是受map支持的,map的变化会在集合中反映出来,反之亦然。当一个迭代器正在 遍历一个集合时,若map被修改了(除迭代器自身的移除操作以外),迭代器的结果会变为未定义。集合支持通过Iterator的Remove、 Set.remove、removeAll、retainAll和clear操作进行元素移除,从map中移除对应的映射。它不支持add和addAll 操作。
2)Collection values():返回一个map中包含的所有value的一个Collection视图。这个collection受map支持的,map的变化会在 collection中反映出来,反之亦然。当一个迭代器正在遍历一个collection时,若map被修改了(除迭代器自身的移除操作以外),迭代器 的结果会变为未定义。集合支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行 元素移除,从map中移除对应的映射。它不支持add和addAll操作。

3)Set<Map.Entry<K,V>> entrySet():返回一个map钟包含的所有映射的一个集合视图。这个集合受map支持的,map的变化会在collection中反映出来,反之 亦然。当一个迭代器正在遍历一个集合时,若map被修改了(除迭代器自身的移除操作,以及对迭代器返回的entry进行setValue外),迭代器的结 果会变为未定义。集合支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行元素 移除,从map中移除对应的映射。它不支持add和addAll操作。

 

 

(6)map分类

 1)HashMap

Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。

HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用CollectionssynchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap

2)Hashtable

HashtableHashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。

3)LinkedHashMap

LinkedHashMap HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

4)TreeMap

TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。

 

一般情况下,我们用的最多的是HashMap,Map中插入、删除和定位元素,HashMap是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列.

 

//////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

 

 

集合:集合是存储对象数据的集合容器。
集合比数组的优势:
1. 集合可以存储任意类型的对象数据,数组只能存储同一种数据类型 的数据。
2. 集合的长度是会发生变化的,数组的长度是固定的。

Collection:单例集合的根接口

 

Collection

Set  

HashSet

TreeSet

List

ArrayList

LinkedList

Vector

 

2.List

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。

其元素以线性方式存储,集合中可以存放重复对象,可以有null元素,

用户能够使用索引(元素在List中的位置,类似于数组下>标)来访问List中的元素,这类似于Java的数组。

基于ArrayListVectorArrayList)适合查询,而LinkedList适合添加,删除操作

 

子类:

ArrayList  由数组实现的List,允许对元素进行快速随机访问。特点: 查询速度快,增删慢。

 

LinkedList 底层是使用了链表数据结构实现的,不是同步的。查询速度慢,增删快。

LinkedList不是基于数组的,所以不受数组性能的限制。

它每一个节点(Node)都包含两方面的内容:

1.节点本身的数据(data);

2.下一个节点的信息(nextNode)。

所以当对LinkedList做添加,删除动作的时候就不用像基于数组的ArrayList一样,必须进行大量的数据移动。

只要更改nextNode的相关信息就可以实现了,这是LinkedList的优势。

 

Vector 是基于数组(Array)的List,线程安全的,操作效率低。

其实就是封装了数组所不具备的一些功能方便我们使用,所以它难易避免数组的限制,同时性能也不可能超越数组。

所以,在可能的情况下,我们要多运用数组。

 

总结:

Vector、ArrayList和LinkedList
大多数情况下,从性能上来说ArrayList最好,但是当集合内的元素需要频繁插入、删除时LinkedList会有比较好的表现,但是它们三个性能都比不上数组,另外Vector是线程同步的。所以:
如果能用数组的时候(元素类型固定,数组长度固定),请尽量使用数组来代替List;
如果没有频繁的删除插入操作,又不用考虑多线程问题,优先选择ArrayList;
如果在多线程条件下使用,可以考虑Vector;
如果需要频繁地删除插入,LinkedList就有了用武之地;
如果你什么都不知道,用ArrayList没错。

 

其它:
一、几个常用类的区别
1.ArrayList: 元素单个,效率高,多用于查询
2.Vector: 元素单个,线程安全,多用于查询
3.LinkedList:元素单个,多用于插入和删除
4.HashMap: 元素成对,元素可为空
5.HashTable: 元素成对,线程安全,元素不可为空

 

 

 

3.Set

是一种不包含重复的元素的无序Collection。
Set:不能包含重复的元素,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

List:是一个有序的集合,可以包含重复的元素。提供了按索引访问的方式。

 

Set的功能方法 

Set具有与Collection完全一样的接口,因此没有任何额外的功能,

实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)

 

Set不保存重复的元素。如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象。

加入Set的元素必须定义equals()方法以确保对象的唯一性。

 

Set是在 HashMap的基础上来实现的,

HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。

HashSet的add(Object obj)方法的实现:

 

public boolean add(Object obj) {   

   return map.put(obj, PRESENT) == null;   

}   

 

因为HashMap的key是不能有重复的,而HashSet的存储方式是把HashMap中的Key作为Set的对应存储项来存储的,

所以Set中的元素不能有重复。

 

 

Set子类:

·HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。 

·TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。 

LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。

于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

  SortedSet 是一个按照升序排列元素的 Set

 

Set和List的区别

Set同List都实现了Collection接口,但是他们的实现方式不同。

List和Set的根本区别,List基本上都是以Array为基础,Set是在 HashMap的基础上来实现的;

Set: 是一种不包含重复的元素的无序Collection。

List:是一个有序的集合,可以包含重复的元素。提供了按索引访问的方式。

 

4.区别

4.1CollectionMap的区别

容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有 key-value pair,像个小型数据库

4.2、各自旗下的子类关系

Collection
     --List:将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同。
           --ArrayList / LinkedList / Vector
     --Set : 不能含有重复的元素
           --HashSet / TreeSet
      Map
     --HashMap
     --HashTable
     --TreeMap

4.3、其他特征

ListSetMap将持有对象一律视为Object型别。

CollectionListSetMap都是接口,不能实例化。
    继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。
vector容器确切知道它所持有的对象隶属什么型别。vector不进行边界检查。

 

总结

1. 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
2. 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
3. 在除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们 的效率更高。
4. 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
 
5. 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。一旦将对象置入容器内,便损失了该对象的型别信息。
6. 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

注意:

1、Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。

2、Set和Collection拥有一模一样的接口。

3、List,可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)

4、一般使用ArrayList。用LinkedList构造堆栈stack、队列queue。

5、Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。

      HashMap会利用对象的hashCode来快速找到key。

6、Map中元素,可以将key序列、value序列单独抽取出来。

使用keySet()抽取key序列,将map中的所有keys生成一个Set。

使用values()抽取value序列,将map中的所有values生成一个Collection。

为什么一个生成Set,一个生成Collection?那是因为,key总是独一无二的,value允许重复。

 

 

原创粉丝点击