填充容器
- new ArrayList<Object>(Collections.nCopies(size, item))和Collections.fill(list, item)
- 一种Generator解决方案
所有Collection子类型都有一个接收另一个Collection对象的构造器,用所接收的Collection对象中的元素来填充新的容器。或者使用Collection.addAll(Generator)。
//适配器模式的实例
public class CollectionData<T> extends ArrayList<T>{
public CollectionData(Generator<T> gen, int quantity){
for(int i = 0; i< quantity; i++){
add(gen.next());
}
}
//a generic convenience method;
public static <T> CollectionData<T> list(Generator<T> gen, int quantity){
return new CollectionData<T>(gen, quantity);
}
}
- Map生成器:
Map可以使用相同方式,但需要一个Pair类。然后使用Generator<Pair<K,V>>的对象填充map。
public class Pair<K,V>{
public final K key;
public final V value;
public Pair(K k, V v){
key = k;
value = v;
}
}
- 使用Abstract类
**享元模式:采用一个共享来避免大量拥有相同内容对象的开销。这种开销中最常见、直观的就是内存的损耗。享元模式以共享的方式高效的支持大量的细粒度对象。java的String对象的创建就是享元模式。
为了创建只读的Map,可以继承AbstractMap并实现entrySet(),为了创建只读的Set,可以继承AbstractSet并实现iterator()和size()。享元在于子类只存储索引,通过索引读取内容。
可选操作
执行各种不同的添加和移除的方法在Collection都是可选操作,如果调用没有实现的方法,会抛出UnsupportedOperationException。这是为了防止接口爆炸。
最常见的未获支持的操作,都来源于背后由固定尺寸的数据结构支持的容器,比如Arrays.asList()将数组转换为List时,就会得到这样的容器,或者Collections.unmodifiableList()返回的容器。所以,应该把这种结果作为构造器参数传递给任何Collection,这样就可以产生尺寸可调整的容器。
Set和存储顺序
Set(interface) | 存入Set的每个元素都必须是唯一的,加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口,Set不保证维护元素的次序。 |
---|---|
HashSet(默认) | 为快速查找而设计的Set。存入HashSet的元素必须定义hashCode() |
TreeSet | 保存次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。元素必须实现Comparable接口 |
LinkedHashSet | 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的顺序)。bianlishi,以插入顺序显示。元素也必须定义hashCode()方法。 |
对于良好的编程风格来说,你应该在覆盖equals()方法时,总是同时覆盖hashCode()方法。
SortedSet接口:比如TreeSet就是其中一个实现。
队列
Queue接口两个实现是LinkedList和PriorityQueue,差异在于排序行为而不是性能。
优先级队列:优先级队列的元素需要实现Comparable。
双向队列:可以在任何一段添加或移除元素。LinkedList包含支持双向队列的方法,但是java标准库中没有这样的接口。
Map
- 性能:
HashMap使用散列码——“相对唯一”来代表对象的int值。如果不能满足你的要求,可以创建自己的Map来进一步提高查询速度。
HashMap* | 基于散列表实现,插入和查询“键值对”的开销是固定的。可以通过构造器设置容量和负载因子,以调整容器的性能。 |
---|---|
LinkedHashMap | 取得键值对是插入顺序,或是最近很少使用(LRU)顺序。只比HashMap慢一点,迭代访问时更快,因为使用链表维护内部次序。以插入顺序返回键值对迭代遍历。 |
TreeMap | 基于红黑树的实现。查看键或键值对时,它们会被排序(次序有Comparable或Comparator决定)。得到结果是经过排序的。唯一带有subMap()的Map,可以返回一个子树。 |
WeakHashMap | 弱键映射,允许释放映射所指向的对象。如果映射之外没有引用指向某个键,该键可以被垃圾回收。 |
ConcurrentHashMap | 线程安全的Map,不设计同步加锁。 |
IndentityHashMap | 使用==代替equals()对键进行比较的散列映射。专为特殊问题设计 |
*任何键都必须具有equals()方法。
*SortedMap接口:TreeMap是其唯一实现。
散列与散列码
HashMap使用equals()判断当前的建是否与表中存在的键相同。
HashMap的性能因子:
- 容量:表中的桶位数
- 初始容量:表在创建时所拥有的桶位数。HashMap和HashSet都具有允许你指定初始容量的构造器。
- 尺寸:表中当前存储的项数
- 负载因子:尺寸/容量。空表的负载因子为0,班满表的负载因子是0.5,负载轻的表产生冲突的可能性小,因此对于插入和查找都是最理想的,但会减慢使用迭代器遍历的过程。HashMap和HashSet都具有允许你指定负载因子的构造器,表示当负载情况达到该负载因子的水平时,容器将自动增加其容量(容量),实现方式是使容量加大一倍,并重新将现有对象分布到新的桶位几种(再散列)。
Collections有用的api
快速报错
java容器有一种保护机制,当你调用iterator()获取迭代器后,再想迭代器所指向的Collection添加点什么,就会抛出ConcurrentModificationException异常。
持有引用
如果想继续持有对某个对象的引用,希望以后还能够访问到该对象,但是也希望能够允许垃圾回收器释放它,这是就应该使用Reference对象。一般是以Reference对象作为你和普通引用之间的媒介(代理),另外一定不能有普通的引用指向那个对象。
Reference抽象类的导出类:SoftReference(内存敏感的高速缓存),WeekReference(目的是“规范映射”,不妨碍垃圾回收器回收映射的键或值,“规范映射”中对象的实例可以在程序的多处被同时使用,以节省存储空间),PhantomReference(调度回收前的清理工作,比Java终止机制灵活),由强到弱排列,对应不同级别的可获得性。PhantomReference只能放入ReferenceQueue,其余两者可选。
补充资料1
补充资料2
Java 1.0/1.1 的容器
- Vector:自我扩展的序列=>ArrayList
- Enumeration:接口,hasMoreElements()、nextElement()。
- HashTable => HashMap
- Stack:继承Vector
- BitSet:高效率的存储大量“开/关”信息,最小容量为long:64位,自动扩容(都是64的倍数),若存储的内容比较小,就浪费了一些空间。补充
网友评论