Java 集合框架

Java 集合框架

  • 1 Collection接口
    • Set接口
    • List接口
    • Queue接口

由于功能与集合框架相似,Map经常与集合放在一起讨论。

  • 2 Map接口
Map主要实现数据结构有序线程安全父类其他特性
HashMap哈希表随机存储线程不安全AbstractMap访问速度快
LinkedHashMap链表有序存储线程安全HashMap遍历比HashMap慢
Hashtable哈希表随机存储线程安全HashMap写入较慢
TreeMap有序存储线程不安全AbstractMap默认是按键值的升序排序,指定排序的比较器

Map接口见->链接


1 Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。
一些 Collection允许相同的元素而另一些不行,一些能排序而另一些不行。
Java JDK不提供直接继承自Collection的类,
Java JDK提供的类都是继承自Collection的“子接口”如List和Set。

所有实现Collection接口的类都必须提供两个标准的构造函数:
第一个:无参数的构造函数,用于创建一个空的Collection;
第二个:带Collection参数的构造函数,用于创建一个新的Collection,新的Collection与传入的Collection有相同的元素;
该构造函数允许用户复制一个Collection。
Collection

1.1 遍历Collection中的元素

Collection接口继承了Iterable接口,不论Collection的实际类型如何,它都支持一个iterator()的方法,
该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个element。
典型的用法如下:

    Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }

由Collection接口派生的接口主要有:List、Set和Queue。
Collection

1.2 List接口

List是有序的,使用此接口能够精确的控制每个元素插入的位置。
用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。
List

1.2.1 List接口主要实现类
List接口主要实现数据结构线程安全其他特性
Vector数组线程安全增删和查询都很慢
Stack数组线程安全后进先出
ArrayList数组线程不安全查询速度快
LinkedList链表线程不安全增删元素的速度很快
1.2.2 LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。
  一种解决方法是在创建List时构造一个同步的List:
    List list = Collections.synchronizedList(new LinkedList(…));

1.2.3 ArrayList类

ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增 加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
  和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

1.2.4 Vector类

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。

ArrayList arrayList = new ArrayList(100);
arrayList.ensureCapacity(200);
Vector vector = new Vector(100);
vector.ensureCapacity(200);
1.2.5 Stack 类

Stack继承自Vector,线程安全什么的跟Vector都差不多,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

有几个地方需要注意:

第一:add()和push(),stack是将最后一个element作为栈顶的,所以这两个方法对stack而言是没什么区别的,但是,它们的返回值不一样,add()返回boolean,就是添加成功了没有;push()返回的是你添加的元素。为了可读性以及将它跟栈有一丢丢联系,推荐使用push。
第二:peek()和pop(),这两个方法都能得到栈顶元素,区别是peek()只是读取,对原栈没有什么影响;pop(),从字面上就能理解,出栈,所以原栈的栈顶元素就没了。

1.3 Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
  请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
  Set集合类的特点就是可以去重,它们的内部实现都是基于Map的,用的是Map的key,所以知道为什么可以去重复了吧。
  比较是基于hascode()方法和equals()方法的,所以必要情况下需要重写这两个方法。
  既然要去重,那么就需要比较,既然要比较,那么就需要了解怎么比较的,不然它将1等于2了,你怎么办?

1.3.1 Set接口主要实现类
Set主要实现数据结构线程安全其他特性
HashSet哈希表线程不安全查询速度最快集合
LinkedHashSet链表线程不安全线程不安全
TreeSet线程不安全有序的
EnumSet不确定线程不安全枚举的专用Set
1.3.2 HashSet

HashSet是散列表的一个实现,存储是无序的,读取也是无序的;
装填因子:load factor=0.75
装填元素超过了容量的%75时,会进行再散列。
看下面例子:

		Set s = new HashSet();
		String[] a = "a,b,c,d,e,f,g".split(",");
		System.out.println(">>myHashSet1>>start");
		for(String aa : a)
			s.add(aa);
		Iterator i = s.iterator();
		while(i.hasNext())
			System.out.println(">>>"+i.next());
		System.out.println(">>myHashSet1>>end");

运行结果:

>>myHashSet1>>start
>>>f
>>>g
>>>d
>>>e
>>>b
>>>c
>>>a
>>myHashSet1>>end

可以看到当一个数组被有顺序的存进一个HashSet后,存储是随机的。

1.3.3 TreeSet

这是一个树结构的Set,存的时候是以树结构(红黑树)存储的,遍历时拿到的是排好序了的。

		Set s = new TreeSet();
		String[] a = "d,c,g,f,a,b,e".split(",");
		for(String aa:a)
			s.add(aa);
		Iterator i = s.iterator();
		while(i.hasNext())
		System.out.println(">>>>"+i.next());

运行结果:

>>>>a
>>>>b
>>>>c
>>>>d
>>>>e
>>>>f
>>>>g

1.4 总结

ArrayList,LinkedList一个无序,一个有序;
HashSet,TreeSet一个无序,一个有序;
HashMap,LinkedHasmMap,一个无序,一个有序;
Vector和HashTable,Stack是线程安全的,但是效率低;
线程不安全的类都可以配合Collections得到线程安全的类。

ArrayList , LinkedList , Vector
ArrayList和Vector本质都是用数组实现的,而LinkList是用双链表实现的;所以,Arraylist和Vector在查找效率上比较高,增删效率比较低;LinkedList则正好相反。
ArrayList是线程不安全的,Vector是线程安全的,效率肯定没有ArrayList高了。实际中一般也不怎么用Vector,可以自己做线程同步,也可以用Collections配合ArrayList实现线程同步。
前面多次提到扩容的代价很高,所以如果能确定容量的大致范围就可以在创建实例的时候指定,注意,这个仅限于ArrayList和Vector。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值