第6章 对象群体的组织
6.1 Java集合框架介绍
- Java集合框架:
对外的接口:表示集合的抽象数据类型;
接口的实现:指实现集合接口的Java类,是可重用的数据结构;
对集合运算的算法:是指执行运算的方法,例如在集合上进行查找和排序; - 集合框架接口:声明了对各种集合类执行的一般操作;
Collection——Set——SortedSet
——List
——Queue
Map——SortMap - Collection接口:实现了一批操作成组对象的方法,实现类AbstractCollection,常用方法:
查询方法int size(),boolean isEmpty(),boolean contains(Object obj),boolean containsAll(Collection c);
修改方法boolean add(Object obj),boolean addAll(Collection<?> c),boolean remove(Object obj),boolean removeAll(Collection c),boolean retainAll(Collection c),void clear();
6.2 主要接口及常用的实现类
- Set接口:对equals和hashCode操作有了更强的约定,两Set对象元素相同则相等;
实现Set接口的类:哈希集合(HashSet),树集合(TreeSet),其他(AbstractSet,ConcurrentSkipListSet,CopyOnWriteArraySet,EnumSet,JobStateReasons,LinkedHashSet); - SortedSet接口:一种特殊的Set,其中的元素是升序排列的,增加了次序相关操作,通常用于存放词汇表之类内容,实现类ConcurrentSkipListSet,TreeSet;
- List接口:可包含重复元素,有序,每个元素有index值(从0开始)标名表中位置;
实现类:Vector,ArrayList(一种类似数组的形式进行存储,随机访问速度极快),LinkedList(内部链表实现,适合于在链表中需要频繁插入和删除操作),栈Stack,其他(…List); - Queue接口:FIFO(先进先出),除了Collection基本操作,还有插入、移除和查看;
实现类:LinkedList(同时实现List),PriorityQueue(按元素值排序的队列),其他(…Queue); - Map接口:用于维护键/值对(key/value pairs),
不能有重复的关键字,每个关键字最多能够映射到一个值;
声明时可以带有两个参数Map<K, V>,其中K表示关键字类型,V表示值类型;
实现类:HashMap,TreeMap,其他; - SortedMap接口:Map的子接口,一种特殊的Map,其中关键字升序排列,通常用于词典和电话目录等;
声明时可以带有两个类型参数SortedMap<K, V>;
实现类:TreeMap,ConcurrentSkipListMap(基于跳表,支持并发);
6.3 常用算法
- 集合运算算法:大多数用于操作List对象,min和max可用于任意集合对象;
- 排序算法sort:
使List元素按某种次序关系升序排列;
简单形式:将元素按照自然次序排列,或集合实现了Comparable接口;
第二种形式需要一个附加的Comparator对象作为参数,用于规定比较规则,可用于实现反序或特殊次序排序;
算法性能:快(时间复杂度nlog(n)),稳定; - 洗牌算法shuffle:
以随机方式重排List元素,任何次序出现的几率都是相等的;
实现偶然性游戏时很有用,如洗牌; - 常规数据处理算法:
reverse:将一个List中的元素反向排列;
fill:用指定的值覆写List中每一个元素,在重新初始化List时有用; - copy:接收目标List和源List两个参数,将源中的元素复制到目标进行覆写,目标List必须至少与源一样长,如更长则多余部分内容不受影响;
- 查找算法binarySearch:
使用二分法在一个有序List中查找指定元素;
一种形式是假定List按照自然顺序升序排列,第二种形式需要增加Comparator对象表示比较规则,并假定List是按照这种规则排序的;
必须能够对List中的元素进行随机访问(检查集合是否实现了RandomAccess接口,是:二分法查找;否:线性查找); - 寻找最值:
用于任何集合对象;
min和max算法返回指定集合中最小值和最大值;
简单形式按照元素自然顺序返回最值,另一种形式需要附加一个Comparator对象作为参数,并按其指定的比较规则返回最值;
6.4 数组实用方法,基于动态数组的类型(Vector, ArrayList)
- Arrays类,java.util.Arrays,常用方法:
fill(type[] a, type val)给数组填充,简单地把一个数组全部或某段数据填成一个特殊的值;
equals(type[] a, type[] b)实现两个数组的比较,相等时返回true;
sort(type[] a)对数组排序;
binarySearch()对数组元素进行二分法查找;
asList(T…a)实现数组到ArrayList的转换;
toString(基本类型或object数组引用)实现数组到string的转换; - Vector, ArrayList:
实现了Collection接口;
能够存储相同类型(或具有相同的父类或接口)的对象;
不能存储基本类型(primitive)的数据,要将基本类型数据包裹在包裹类中;
其容量能够根据空间需要自动扩充;
增加元素方法的效率较高,除非空间已满(这种情况需先扩容); - Vector:集合框架中的遗留类,旧线程安全集合(不鼓励使用);
ArrayList方法是非同步的,效率较高;
新版本JDK提供了线程安全集合Java.util.concurrent包,映像、有序集、队列;
任何集合类通过使用同步包装器可以变成线程安全的:List synchArrayList = Collections.synchronisedList(new ArrayList(); - ArrayList构造方法:
ArrayList()构造一个空表,默认容量为10;
ArrayList(Collection<? extends E> c)用参数集合元素为初始值构造一个表;
ArrayList(int initialCapacity)构造一个空表,容量为initialCapacity; - ArrayList其他方法(参考JavaAPI文档);
6.5 遍历Collection
- 遍历实现了Collection接口的集合:
通过Enumeration及Iterator接口遍历集合;
增强for循环遍历集合;
通过聚集操作遍历集合; - 通过Enumeration及Iterator接口遍历:
Enumeration/Iterator能够从集合类对象中提取每一个元素,并提供了用于遍历的方法;
Java中许多方法(如elements())都返回Enumeration类型对象,而不返回集合类对象;
Enumeration接口不能用于ArrayList对象,Iterator接口既可用于ArrayList对象也可用于Vector对象; - Iterator接口:
对Enumeration接口(旧版本)的改进,因此优先选用;
具有从正在遍历的集合中去除对象的能力;
具有实例方法:hasNext()是否还有元素,next()取得下一个元素,remove()去除一个元素(从集合中去除最后调用next()返回的元素,而不是从Iterator类中去除); - 用增强for循环遍历for(Type a:集合对象);
- 通过聚集操作遍历:聚集操作与lambda表达式一起使用;
6.6 Map接口及其实现
- Map接口:
用于存储关键字(key)和值(value)的元素对,其中每个关键字映射到一个值;
当需要通过关键字实现对值的快速存取时使用;
抽象方法主要有查询方法、修改方法;
主要实现类HashTable(1.0),HashMap(1.2); - Map接口的查询方法:int size(),boolean isEmpty(),boolean containsKey(Object key),boolean containsValue(Object val),Object get(Object key),Collection(),Set keyset(),Set entrySet();
- Map接口的修改方法:
Object put(Object key, Object val)将给定的关键字/值加入Map对象中(key必须唯一,否则会取代已有值);
void putAll(Map m)将给定参数Map中所有项加入到接收者Map对象中;
Object remove(Object key)将关键字为给定参数的项从Map对象中删除;
void clear()从Map对象中删除所有项; - 哈希表(HashTable,HashMap):散列表,用来存储群体对象的集合类结构;
- 哈希表存储对象的方式:对象的位置和对象的关键属性k之间有一个特定对应关系f(哈希Hash函数),它使每个对象与一个唯一的存储位置相对应,因而查找时根据关键属性k计算f(k)的值即可得到存储位置;
- 哈希表概念:
容量(capacity),哈希表容量不固定,随对象加入可以自动扩充;
关键字/键(key),每个存储对象需要有一个关键字key,key可以是对象本身,也可以是对象的一部分(如对象某一个属性);
哈希码(hash code),要将对象存储到HashTable,需要将其关键字key映射到一个整型数据,成为key的哈希码;
哈希函数(hash function),返回对象的哈希码;
项(item),哈希表中每一项都有两个域(关键字域key及值域value,即存储的对象),key和value都可以是任意的Object类型对象,但不能为空,HashTable所有关键字唯一;
装填因子(load factor),表中填入的项数/表的容量; - 哈希表构造方法:
HashMap(),默认容量16,默认装填因子0.75;
HashMap(int initialCapacity)容量initialCapacity,默认装填因子0.75;
HashMap(int initialCapacity, float loadFactor)自定义容量和装填因子;
HashMap(Map <? extends K, ? extends V> m)以参数m为初值构造新的HashMap。