java 中的集合(一) 概述

java集合工具包位于java.util包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。Java集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。

需要强调的是,集合类容纳的是对象,不是基本类型,也不是变量(或者说引用),不能直接对某个成员赋值。如果需要改变某个对象,需要使用集合类提供的赋值方法(比如put),而数组可以直接赋值或操作(如自增等)。因为集合容纳的是对象,所以也支持下面的写法:

    list.get(index).leftChild = null;  

但不支持这种写法:

    //list.get(index) = null;//error  

可以先看几张集合框架的关系图。

《Thinking in Java》 给出的图:


网友改进版(来源于:http://blog.csdn.net/ns_code/article/details/35564663):

Collection关系图(来源于:http://blog.csdn.net/u014136713/article/details/52089156):


Map关系图(来源于:http://blog.csdn.net/u014136713/article/details/52089156):

当然,上面的这些图都只是列了重点,并不能反映集合框架的全部功能。

未支持的操作

为了避变接口冲突以及接口数量过于庞大(或者说集合类源码实现太过复杂),并不是所有的实现类都完整实现了接口的每个方法。因为集合框架在设计之初,就约定了某些方法仅仅是可选的。可以看下面这个例子:

class Unsupported {
	private static String[] s = { "one", "two", "three", "four", "five", "six",
			"seven", "eight", "nine", "ten", };
	static List a = Arrays.asList(s);
	static List a2 = Arrays.asList(new String[] { s[3], s[4], s[5] });

	public static void main(String[] args) {
		System.out.println("a.contains(" + s[0] + ") = " + a.contains(s[0]));
		System.out.println("a.containsAll(a2) = " + a.containsAll(a2));
		System.out.println("a.isEmpty() = " + a.isEmpty());
		System.out.println("a.indexOf(" + s[5] + ") = " + a.indexOf(s[5]));
		
		// Compiles, and run:
		ListIterator lit = a.listIterator(a.size());
		while (lit.hasPrevious())
			System.out.print(lit.previous());
		System.out.println();
		for (int i = 0; i < a.size(); i++)
			a.set(i, "47");
		
		// Compiles, but won't run:
		lit.add("X"); // Unsupported operation
		a.clear(); // Unsupported
		a.add("eleven"); // Unsupported
		a.addAll(a2); // Unsupported
		a.retainAll(a2); // Unsupported
		a.remove(s[0]); // Unsupported
		a.removeAll(a2); // Unsupported
	}
}

以 lit.add("X"); 来说,lit对象对应的class,本质上是AbstractList中的一个内部类:

 private class ListItr extends Itr implements ListIterator<E> {}

虽然接口ListIterator中确实有add方法,但AbstractList.ListItr是这么实现的:

public void add(E e) {

   checkForComodification();

	    try {
		AbstractList.this.add(cursor++, e);
		lastRet = -1;
		expectedModCount = modCount;
	    } catch (IndexOutOfBoundsException ex) {
		throw new ConcurrentModificationException();
	    }
	}

其中调用了外部类的add方法,AbstractList没有实现add方法:

 public void add(int index, E element) {
	throw new UnsupportedOperationException();
    }

上面这种情况,主要是因为 List a 是由数组转变而来的,设计之初就不希望后续有增删的操作(可近似理解为只读),但是可以遍历取值。如果要进行add等约定之外的操作,就会抛出UnsupportedOperationException。

这样做的一个缺点是编译期间并不会报错,运行过后才会发现问题。不过好在,最常用的集合类,如ArrayList,LinkedList和HashMap,都基本实现了对应接口中的所有方法(并有大量扩展,大大丰富了使用场景),正常情况下不用担心这个问题。

初始大小

在java集合框架中的大部分类的大小是可以随着元素个数的增加而相应的增加的,我们似乎不用关心它的初始大小,但如果我们考虑类的性能问题时,就一定要考虑尽可能地设置好集合对象的初始大小,这将大大提高代码的性能。

比如,HashMap缺省的初始大小为16,载入因子为0.75,即如果其中的元素个数超过12个,它就必须进行扩容操作,所以,如果你知道在创建一个新的HashMap对象时就知道元素的确切数目,最好合理设置初始大小和载入因子。

以下是就具体的内容分别研究:

List相关:链接

ArrayList源码分析:链接

Vector源码分析:链接

LinkedList源码分析:链接

BitSet源码分析:链接

(注:BitSet并不属于集合框架,但与List有一定类似性)

Stack源码分析:链接

Set&&Map相关:链接

HashSet源码分析:链接

LinkedHashSet源码分析:链接

TreeSet源码分析:链接

HashMap源码分析:链接

LinkedHashMap源码分析:链接

TreeMap源码分析:链接

迭代器:链接

…………………………………………………………………………………………………………

concurrent并发包集合:链接


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值