Java中的集合

来源:互联网 发布:尼康镜头大三元知乎 编辑:程序博客网 时间:2024/05/21 14:42

一、概述

java中具有一整套多集合框架,包括Collection和Map两大类,也是集合层次中的根元素,它们在java中都是接口。


二、Collection

Collection接口派生出Set、Queue、List三种接口,即三种规范。

其中Set表示无序集合,不能包含重复的元素;Queue表示队列或栈;List表示有序集合,可以包含重复的元素。

遍历Collection中的元素可以使用Iterator遍历器,或者for-each循环,在遍历Collection的过程中,不能修改正在遍历对那个Collection对象,否则会发生异常,但是可以使用Iterator对象删除上一次访问的元素。

2.1、Set

Set接口定义的规范为:不能包括重复元素,元素没有顺序。

直接实现Set接口的类有有HashSet、EnumSet,HashSet还有一个子类LinkedHashSet。

继承自Set接口的有SortedSet接口,定义的规范为:不能包括重复元素,元素有序,SortedSet接口的实现类有TreeSet。

2.1.1、HashSet

HashSet按照hashCode来决定元素的存储位置,也根据hashCode来访问元素,所以具有较好的存取、查询性能。

HashSet中判断两个元素相等的条件是:两个元素通过equals()方法返回true时,通过hashCode()方法返回的值也相等。如果两个元素通过equals()返回false但通过hashCode()返回true,那么两个元素就会在以链表对形式存入集合中的同一个位置,这会降低HashSet操作到性能。

HashSet存储的是类的引用,如果这个类又是可变类,那么可以修改已经加入HashSet中的元素,从而导致存在两个相等的元素,这不符合Set的规范,所以应该尽量保证加入HashSet中的元素是不可变类的实例,或者不修改元素的属性,否则会导致代码出现意想不到的错误结果。

HashSet只能放入同一个类的实例,允许元素为null。

2.1.2、LinkedHashSet

LinkedHashSet继承自HashSet,也根据hashchode来判断存储元素的位置,其中维护了一张链表,所以集合中元素的顺序与插入的顺序一样。

因为要维护链表,所以LinkedHashSet执行插入、删除开销比HashSet大,但是遍历集合中元素时效率高。

2.1.3、EnumSet

EnumSet中的元素只能是同一个枚举类的枚举值,否则会抛出异常,其中元素的顺序为枚举值在枚举类中声明的顺序。

EnumSet没有提供构造方法来创建实例,但是提供来一系列的静态方法来创建EnumSet实例,包括根据传入的Collection、Enum来产生实例。

2.1.4、TreeSet

TreeSet实现了SortedSet接口,SortedSet接口继承自Set接口。

TreeSet中元素默认按照从小到大的顺序排序,使用默认排序时元素所属的类必须实现Comparable接口中的compareTo()方法,由此方法比较元素的大小。TreeSet也可以自定义排序规则,自定义排序规则需要在创建TreeSet对象时传入一个Comparable对象,由此对象提供排序规则,与元素所属的类是否实现Comparable接口以及接口的实现无关。

Comparable接口中只有一个int compareTo(T another);方法,此方法的返回值表示与元素another比较的结果:0:相等,1:大于another,-1:小于another对象。

2.1.5、几种Set的性能分析

HashSet的性能总是比TreeSet好,一般建议使用HashSet,但是TreeSet可以对元素顺序,所以如果需要按照某种规则排序的集合,应该使用TreeSet。

EnumSet是性能最好的,但是其只能存储一个枚举类的枚举值,EnumSet在进行批量操作时(批量插入、批量删除)性能更好。

Set的直接/间接实现类都不是线程同步的集合,如果需要线程同步功能,需要利用Collections提供的方法,Collections提供了下述静态方法把普通的集合转换成线程同步的集合:

public static <T> Collection<T> synchronizedCollection(Collection<T> collection);public static <T> List<T> synchronizedList(List<T> list);public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map);public static <E> Set<E> synchronizedSet(Set<E> set);public static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> map);public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set);

但是即使使用了线程同步的集合,使用iterator或for-each遍历集合的过程中,如果其它线程修改这个集合,会出现ConcurrentModificationException,这种情况下你可以使用以Concurrent开头的集合,比如ConcurrentHashMap、ConcurrentSkipListSet等。

2.2、Queue

Queue表示队列,它的实现类有PriorityQueue。

Deque继承自Queue,表示双端队列,它的实现类有LinkedList。

BlockingQueue继承自Queue,可以用于线程间的的消息投递,它的put、take方法都是线程阻塞的。它的实现类有LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue、PriorityBlockingQueue等几种。

2.2.1、PriorityQueue

PriorityQueue实现了Queue,它表示比较标准队列,因为元素不是按照元素加入对列的顺序排列,而是按照元素的大小排列,就像TreeSet一样,提供自然排序、指定排序。

2.2.2、LinkedList

LinkedList实现了Deque,Deque继承自Queue,它使用链表来存储元素,可以当作栈来使用。

2.3、List

List表示的集合会按照元素添加的顺序进行排序。

List的直接实现类有ArrayList、LinkedList、Vector等。Vector还有一个子类Stack,二者都是java 1.0就有的集合,很多方法都已经过时,因为它们具有线程同步功能,所以性能不好,不推荐使用Vector和Stack,如果需要使用栈功能,应该使用LinkedList。

List提供了ListIterator,可以逆向遍历List。List不是线程同步的,如果要实现线程同步,可以使用Collections中的方法。


三、Map

Map以key-value的形式存储元素,其中key不可以相同,但是value可以相同。Map中的key用Set存储,所以Map的种类与Set的种类很类似,实际上,java中先有了Map规范,然后将其中的value置为null,就是Set规范。

3.1、HashMap、Hashtable

HashMap、Hashtable类似ArrayList与Vector的关系,Hashtable是很早提供的类,具有线程同步功能,效率较低,不建议使用了,而且它的命名没有遵循java规范。

Hashtable中的key不能为null,HashMap中的key可以为null。

HashMap不可以包含key相同的value,判断key是否相同的标准是:两个key通过equals()方法返回true时,通过hashCode()方法也返回true。

3.2、TreeMap

TreeMap可以根据key对其中的元素排序,排序规则和TreeSet类似,有默认排序和自定义排序两种。

3.3 EnumMap

EnumMap中元素的key必须是同一个Enum类的枚举值。

四、广告

  • 手机如何连电脑?
  • 如何与电脑互发文件?
  • 如何与电脑互发文字?
  • 如何推送通知到电脑?
  • 电脑如何远程控制手机的相机?

快牙网传——全部搞定!

不想试试吗?
在豌豆荚等应用商店搜索“快牙网传“,或立即下载 Apk,也可以扫码下载。
这里写图片描述

0 0
原创粉丝点击