Java容器类的选择

1 大类别的选择

  • 当想要装非重复元素时,选择set
  • 当想要保证装入的顺序时,选择List
  • 当要以Key-value的形式存储时,选择Map
  • 当想要保证元素先进先出时,选择Queue

2 set集合之间的选择

  • HashSet:是不保证元素的排列顺序的,并且是线程不安全的,且集合元素可以为null。
  • LinkedHashSet:将会按元素添加的顺序访问元素。由于LinkedHashSet需要维护元素的插入顺序,因此性能差于HashSet但在迭代访问元素时,有很好的性能。
  • TreeSet:利用红黑数来存储元素,保证集合中的元素处于有序状态(排序规则有自然排序-comparable和定制排序comparator)。所以在需要进行元素排序(不是按它的插入顺序哈!!!)时,选择它。
  • EnumSet:转为枚举类设计的集合类,EnumSet中元素必须是指定枚举类的值。

性能比较,一般情况下:
EmumSet好与HashSet好于LinkedHashSet好于TreeSet
需要注意的是,HashSet,LinkedHashSet,TreeSet,EmumSet都是线程不安全的,且添加元素可以为null。需要手动保证Set集合的同步性。通常可以使用Collection的synchronizeSet方法还”包装“Set集合,此操作最好在创建Set时进行。例子:

public class Main {
	public static void main(String[] args) {
		//set是线程不安全的,插入元素可以为空
		Set<Integer> s = new LinkedHashSet<Integer>();
		s.add(null);
		HashSet<Integer> hs = new HashSet<Integer>();
		hs.add(null);
		TreeSet<Integer> ts = new TreeSet<Integer>();
		ts.add(null);
		EnumSet e = EnumSet.allOf(teacher.class);
		e.add(null);
	}
}
enum teacher {
	A, B, C, D
}

3 List之间的选择

  ArrayList和Vector都是List接口的两种实现,都是通过动态的运行在分配的Object数组实现的。ArrayList和Vector提供了重新分配Object[]数组的方法。
  Vector有很多缺点,通常推荐使用ArrayList。ArrayList是线程不安全的,Vector是线程安全的,因此ArrayList的性能要比Vector的性能好。
  其实Arrays工具中提供了一个==asList(Object……a)==方法将数组或多个参数转换为一个List集合。这个List不是ArrayList和Vector的实例,而是Arrays中的内部类Arrays.ArrayList的实例,他是固定长度的,只能访问元素,而不能改变元素的个数。例子:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer> l= Arrays.asList(new Integer(3),new Integer(2));
		System.out.println(l);
		l.add(new Integer(1));//会报这个异常,Exception in thread "main" java.lang.UnsupportedOperationException
		System.out.println(l);
	}

  LinkedList,若有频繁插入删除元素,选择LinkedList;若要随机访问元素,选择使用ArrayList。但是,总体来说ArrayList的性能要由于LinkedList的。
  对于遍历,对ArrayList,Vector进行遍历时,采用随机访问方法get()遍历元素,性能更好。对LinkedList集合,采用迭代器Iterator进行遍历性能更好。

4 Queue之间的选择

  PriorityQueue是Queue接口的一个实现类。它保存队列的顺序是按队列元素之间的大小顺序进行的,而不是按加入队列的顺序保存的。Priority不允许插入null值。当然它也有自然排序和订制排序两种排序方式。
  Deque接口是Queue的子接口,它有一个实现类ArrayDeque,它即可以当做队列使用,也可以当做栈来使用。它的底层实现机制与ArrayList相似,也是采用一个可以重新调整大小的Object数组来保存元素的。注意,要使用这种数据结构时,推荐使用ArrayDeque和后面讲到的LinkedList,不要使用Stack!!!.
  LinkedList类是List接口的实现类,也是Deque接口的实现类。它也可以作为双端队列来使用,因此也可以当做栈、队列来使用。LinkedList的实现机制是以链表的形式来保存元素的

5 Map之间的选择

  Map中key和value可以是任意引用类型的数据,其中key不允许重复。Map中有一个==keySet()==方法,用于返回key组成的set集合。其实我们对待Map可以像对待Set一样,因为Map是提供一个Entry的内部类来封装key-value的。Map也重写了toString()方法。

  与HashSet相似,在HashMap,HashSet使用可变对象作为key时,当程序修改了作为key的可变对象后,程序再也无法访问到Map中被修改过的key了。因此尽量不要使用可变对象作为HashMap,HashTable,HashSet的key。

  WeakHashMap的key保留的是实际对象的弱引用(HashMap的key保留的是实际对象的强引用)。这就意味着如果WeakHashMap对象的key所引用的对象没有被其它强引用变量引用时,则这些Key所引用的对象可能被垃圾回收机制回收,WeakHashMap也会删除相应的key-value。当然,既然使用了WeakHashMap的key保存对象弱引用,就不要让该对象有任何强引用,否则使用WeakHashMap就没意义了。

  IdentityHashMap与HashMap的区别在于,IdentityHashMap当且仅当key严格相等(key1==key2)才认为两个key相等。而HashMap是认为key1和key2只要equals(),hashCode()相等,则认为两个key相等。例子:

public static void main(String[] args) {
		IdentityHashMap ihm = new IdentityHashMap();
		ihm.put(new String("wobushixiaobailian"), 99);
		ihm.put(new String("wobushixiaobailian"), 89);
		ihm.put("java", 99);
		ihm.put("java", 19);
		System.out.println(ihm);
	}

输出结果:
在这里插入图片描述
  各个Map的性能:EnumMap优于HashMap优于LinkedHashMap优于TreeMap。IdentityHashMap性能没有特别出色之处。

  说到HashSet和HashMap的性能选项,就想到了负载因子(当前hash表的记录数除以当前hash表的容量:size/capacity)。hash表还有一个负载极限,它是一个0~1的数,当负载因子达到负载极限时,hash表会成倍的增加hash表的容量(桶的数量),这个过程叫做rehashing。负载极限的默认值为0.75。如果一开始就知道HashMap或HashSet会存大量的记录,可以初始化一个很大的容量,这样可以增加添加记录的效率,但是初始容量设置太高可能会浪费空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值