您的位置:首页 > 编程语言 > Java开发

关于java中List、Set、Map的一些总结

2014-02-14 16:00 656 查看
今天上班上午把任务做完,下午闲来无事研究了一下List、Set、Map三个集合接口首先List

List

List是Java中的一个接口,继承了Collection接口。它是一个有序集合,又称序列,允许存储重复元素。其实现类常用的有ArrayList、LinkedList等。ArrayList是实现了List接口的可变长数组。它的特点是add方法操作时间复杂度为分期常量时间(amortized
constant time),意思即如果添加n个元素则耗时O(n),其它操作耗时则是线性时间。每个ArrayList都有个容量,即存放元素能力的大小。这个容量是list中元素个数。当添加新的元素时,这个容量也会自动添加,这需要消耗一定时间。如果要添加大量数据到ArrayList,可以先调用ensureCapacity操作,从而减少每次添加新元素容量自动调整的时间。

需要注意的是ArrayList并不是线程同步的。如果多个线程同时访问一个ArrayList实例,至少一个线程修改了其结构(添加或删除元素,或显式的调整了其大小,仅仅设置元素值并不属于结构修改),则会使程序进入不确定的状态。解决方式之一就是使用一个线程同步的对象来封装该ArrayList。或者也可以用Collections.synchronizedList来封装。

List list = Collections.synchronizedList(new ArrayList(...));

实现原理就是Collections.synchronizedList返回的类的iterator做了特殊处理。如果iterator被创建后,除了自己的add和delete方法,有其他行为导致了List结构被修改,iterator将会抛出一个ConcurrentModificationException异常。当然iterate这种处理方式并不能担保它能处理所有的异步并发修改,只能降低程序陷入不确定状态的概率。

LikedList是一个双重链表,它既实现了List接口,也实现了Deque接口。LikedList也不是线程安全的,解决方式与ArrrayList基本相同。

Set

Set也是Java中的一个接口,同样继承于Collection。与List不同的是,Set不允许放置重复元素,并且最多只能放置一个null元素。其实现类有HashSet、TreeSet等。

HashSet的实现其实是依托了一个HashMap的实例。HashSet并不保证元素的迭代顺序每次都是一致的。HashSet的基本操作(add,remove,contains及size)耗时都是常数时间,即迭代Set的耗时与Set的大小乘以HashMap实例的乘积成正比。HashSet也不是线程安全的。

Map

Map则是另一种重要的数据结构,是一组键值对的集合。Map不允许有重复的key存在。 它的实现中有HashTable和HashMap。两者非常相似,最大的不同是HashMap不是线程安全的,并且允许null值作为key或value,而HashTable则不允许。

HashMap的性能取决于两个因素:一个是初始容量,一个是负载因数。容量是哈希表中bucket的数量。初始容量则是HashMap被创建时容量。负载因数则是当容量需要自动增加的阀值。当HashMap中的元素超过了负载因数和当前容量的乘积,HashMap则会重新进行hash计算,以便bucket数量增加到以前的近似两倍。一般负载因子的默认值是0.75,这能达到时间和空间的一个平衡。负载因子过大,虽然会减少空间消耗,但是增加查找时间。

我写了一个小程序来测试三个接口遍历集合元素的结果

import java.util.ArrayList;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

public class SetTest {

public static void main(String[] args) {

//set集合的创建和遍历

Set<Integer> set = new HashSet<Integer>();

set.add(1);

set.add(2);

// System.out.println(set.size());

Iterator<Integer> it = set.iterator();

while(it.hasNext()){

Integer i = it.next();

System.out.println(i);

}

//map

Map<String, Object> map = new HashMap<String, Object>();

map.put("1", 1);

map.put("2", 2);

for(Object obj : map.keySet()){

System.out.println(map.get(obj));

}

//list

List<String> list = new ArrayList<String>();

list.add("1");

list.add("2");

for (int i = 0; i < list.size(); i++) {

System.out.println(list.get(i));

}

}

}

运行发现Set接口遍历后元素的顺序是2,1 list和map遍历结果都是1,2,当set中存在重复元素时,它会自动的去重比如一下代码

Set set = new HashSet();

set.add(1);

set.add(1);

System.out.println(set.size());

其运行结果是1

如果加入一个null

set.add(null);

结果是2

但是当再添加一个null元素时

set.add(null);

运行结果还是为2,由此说明set集合只允许一个null值,并且不允许重复的元素出现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: