[疯狂Java讲义精粹] 第六章|Java集合

0. Java集合分Set、List、Map和Queue. Set是无序, 不可重复的集合; List有序, 可重复; Map具有映射关系; Queue代表队列集合. 

1. 集合类主要用于保存、盛装其他数据, 因此集合类也叫容器类. (集合类在java.util包下. (java.util.concurrent包下有一些多线程支持的集合类)).

  1. 数组元素可以使基本类型的值, 也可以是对象; 集合只能保存对象. (所言对象, 都指对象的引用变量.) 
  2. 集合类主要由两个接口派生而出: Collection 和 Map. (Map保存key-value对, key不能重复.)
2. Collection是List、Set和Queue接口的父接口. 常用方法:
  1. boolean add(Object o)
  2. boolean add(Collection c): 把集合c里的所有元素添加到指定集合里. 如果集合对象被添加对象改变了, 则返回true. 
  3. void clear(): 清除所有元素, 将长度变为0. 
  4. boolean contains(Object o) 
  5. boolean containsAll(Collection c): 返回集合里是否包含集合c里所有元素. 
  6. boolean isEmpty(): 是否为空. 长度0则返回true.
  7. Iterator iterator(): 返回一个Iterator对象, 用于遍历集合里的元素.
  8. boolean remove(Object o): 删除集合中指定元素o. 包含多个元素o时, 全删, 返回true.
  9. boolean removeAll(Collection c): 删除集合c中所有元素. 成功删除一个或以上时, 返回true.
  10. boolean retainAll(Collection c): 从集合中删除c中不含的元素. 如果改变了调用该方法的集合, 返回true. 
  11. int size(): 返回元素个数. 
  12. Object[] toArray(): 把集合转换成一个数组. 
3. System.out.println( c ); 输出集合对象时, 以[ele1, ele2, ele3, ...]形式输出. 

4. Iterator接口也是集合框架的成员, 与Collection和Map接口不同的是Iterator主要用于遍历(迭代访问)Collection集合中的元素, Iterator对象也称跌倒器. 
  1. 常用方法:
    - bollean hasNext(): 如果遍历还没完成, 返回true.
    - Object next(): 返回下个元素.
    - void remove(): 删除集合里上一次next方法返回的元素. 
  2. 使用Iterator对集合元素迭代时, 没有把元素本身传给迭代变量, 而是把集合元素的值传给迭代变量, 所以修改迭代变量的值对集合元素本身谬影响. 
  3. 使用Iterator迭代过程中, 不能修改集合元素(可以用Iterator的remove方法), 否则引发异常(不一定报错. "一旦迭代过程中检测到该集合已经被修改(通常是程序中的其他线程修改), 立即引发java.util.ConcurrentModificationException错误."). 
5. foreach循环: 用来迭代访问Collection集合的元素. 
import java.util.*;

public class IteratorErrorTest
{
	public static void main(String[] args) {
		Collection books = new HashSet();
		books.add("aaaaa");
		books.add("bbbbb");
		books.add("ccccc");
		Iterator it = books.iterator();
		while(it.hasNext())
		{
			String book = (String) it.next();
			System.out.println(book);
			if(book.equals("bbbbb"))
			{
				books.remove(book);    // *1
			}
		}
	}
}
与Iterator接口迭代访问类似(指上面的4.2和4.3). 

6. Set集合.
  1. Set集合与Collection基本一样(行为略有不同, Set不允许包含重复元素), 没有提供任何额外的方法. 
  2. Set判断两对象是否相同用equals, 同时还需要他们的hashCode()方法返回值相等. 
7. HashSet类时Set接口的实现, 按Hash算法来存储集合中的元素, 因此存取和查找性能良好. 
  1. 集合元素可以使null. 
  2. HashSet不是同步的(两个或更多线程同时修改了HashSet集合时, 必须通过代码来保证其同步.). 
  3. 存入元素时, 会调用hashCode()方法计算hashCode值, 决定该对象在HashSet中的存储位置. 
  4. 需要重写对象的equals()方法时, 也要重写hashCode()方法(规则是, equals()返回true时, hashCode值也应相等.). 
  5. HashSet中每个能存储元素的"槽位(slot)"通常称为"桶(blucket)", 如果多个元素hashCode值相同, 但equals()返回false, 就需要在一个"桶"放多个元素, 导致性能下降. 
  6. 重写hashCode()方法的基本规则: 
    - 运行过程中, 同一个对象多次调用hashCode()方法应返回相同值. 
    - 两对象用equals()方法比较返回true时, 他俩的hashCode值应相等. 
    - 对象中用作equals()方法比较标准的Field, 都应用来计算hashCode值. 
8. LinkedHashSet类, 是HashSet类的子类. 它也是用hashCode值来决定元素的存储位置, 但同时使用链表维护元素的次序, 使得元素看起来像是以插入顺序保存的(遍历时将按元素添加顺序来访问集合里的元素). 由于要维护链表, 性能略低于HashSet, 却也因为维护链表, 迭代时性能很好. 
9. TreeSet类, 是SortedSet接口的实现类, 可以确保元素处于排序状态. 
  1. 与HashSet相比, TreeSet提供了几个额外方法:
    - Comparator comparator():  如果TreeSet采用了定制排序, 返回定制排序所使用的Comparator; 否则返回null. 
    - Object first(): 返回集合中的第一个元素. 
    - Object last()
    - Object lower(Object e): 返回位于指定元素前的一个元素( 即小雨指定元素的最大元素, 参考元素不需要时TreeSet集合里的元素). 
    - Object higher(Object e)
    - SortedSet subSet(fromElement, toElement): 返回此Set的子集, 从fromElement(包含) 到 toElement(不包含). 
    - SortedSet headSet(toElement): 返回子集, 由小于toElement的元素组成.
    - SortedSet tailSet(fromElement): 子集, 有大于或等于fromElement的元素组成. 
  2. TreeSet采用红黑树的数据结构存储集合元素. 排序方法有 自然排序和定制排序. 
  3. 自然排序: 调用集合元素的compareTo(Object obj)方法比较大小, 升序排列. 
    - obj1.compareTo(obj2); 返回0表相等, 正整数表obj1>obj2, 负整数表示...
    - 试图把一个对象添加到TreeSet时, 该对象必须实现Comparable接口, 否则抛出异常. 
    -----------------------------------实现了Comparable接口的常用类-----------------------
    1. BigDecimal、BigInteger以及所有的数值型对应的包装类: 按数值大小比. 
    2. Character: 按对应UNICODE值比. 
    3. Boolean: true > false. 
    4. String: 按字符串中的UNICODE值比(一个个的比).  
    5. Date、Time: 后面的时间比前面的大. 
    -------------------------------------------------------------------------------------------------------
    - 添加时, 该元素必须与集合中其他元素时同一类的实例(因为compareTo()方法只能比较同类).
    - TreeSet判断两对象相等的唯一标准: compareTo(Object obj)方法是否返回0. 返0则相等. 
  4. 定制排序: 通过Comparator接口里的compara(T o1, T o2)方法比较o1和o2的大小:o1>o2返回正整数, 小于返负整数, 等返0. 
    import java.util.*;
    
    class M
    {
    	int age;
    	public M(int age)
    	{
    		this.age = age;
    	}
    	public String toStrig()
    	{
    		return "M[age:" + age + "]";
    	}
    }
    public class TreeSetTest4
    {
    	public static void main(String[] args)
    	{
    		TreeSet ts = new TreeSet(new Comparator()
    			{
    				public int compare(Object o1, Object o2)
    				{
    					M m1 = (M) o1;
    					M m2 = (M) o2;
    					return m1.age > m2.age ? -1
    						: m1.age < m2.age ? 1 : 0;
    				}
    			});
    		ts.add(new M(5));
    		ts.add(new M(-3));
    		ts.add(new M(9));
    		System.out.println(ts);
    	}
    }

10. EnumSet类是为枚举类设计的集合类, 其元素都必须是指定枚举类型的枚举值. EnumSet集合是有序的(EnumSet以枚举值在Enum类内的定义顺序来决定集合元素顺序). 

  1. EnumSet集合不允许加入null元素. 
  2. EnumSet类没有暴露任何构造器来创建实例, 应该用它的static方法来创建EnumSet对象. 常用的有:
    - static EnumSet allOf(Class elementType): 创建一个包含指定枚举类里所有枚举值的EnumSet对象. 
    - static EnumSet complementOf(EnumSet s): 创建一个元素类型与s里元素相同的EnumSet集合, 其元素是s所不含的、这个枚举类型里的其他元素(新集合的元素 + s里的元素 = 该枚举类的所有元素). 
    - static EnumSet copyOf(Collection c): 使用普通集合创建EnumSet集合. 
    - static EnumSet copyOf(EnumSet s): 复制一个. 
    - static EnumSet noneOf(Class elementType): 创建一个元素类型为指定枚举类型的空EnumSet. 
    - static EnumSet of(E first, E... rest): 创建一个包含一个或多个枚举值的EnumSet集合, 传入的多个枚举值必须属于同一个枚举类. 
    - static EnumSet range(E from, E to): 创建一个包含从from(包含)枚举值到to(包含)枚举值范围内的所有枚举值的EnumSet集合. 
11. Hash比TreeSet性能好(TreeSet要用红黑树维护集合元素次序), 需要一个保持排序的Set时才需要TreeSet. 

12. List 元素有序, 可重复, 每个元素又对应的顺序索引(默认按添加顺序设置索引, 从0开始). 
  1. 常用方法: 
    - void add(int index, Object element): 把element插入到index处.
    - boolean addAll(int index, Collection c): 把c的所有元素插入到index处. 
    - List subList(int fromIndex, int toIndex): 返回从索引的fromIndex(包括)到toIndex(不包括)的元素组成的子集合. 


    - 不拉不拉不拉不拉...
  2. List用equals比较两对象是否相等. 
  3. List额外提供了一个listIterator()方法, 返回一个ListIterator对象(ListIterator接口继承了Iterator接口, 提供了专门操作List的方法.). 比Iterator增加了:
    - boolean hasPrevious(): 返回该迭代器关联的集合是否有还有上一个元素. 
    - Object previous()
    - void add(): 在指定位置插入一个元素. 
13. ArrayList和Vector类都是基于数组实现的List类, 它们封装了一个动态的、允许在分配的Object[]数组. ArrayList和Vector对象使用initialCapacity参数来设置该数组的长度, 当添加的元素超出了该数组的长度时, initialCapacity自动增加. 如果创建空的ArrayList和Vector集合时不指定initialCapacity参数, 则Object[]数组长度默认为10. 还有两个方法重新分配Object[] 数组. - void ensureCapacity(int minCapacity): 将集合的Object[]数组长度增加minCapacity.     - void trimToSize(): 调整ArrayList和Vector集合的Object[]数组长度为当前元素个数. (Vector很古老, JDK1.0时就有. 通常尽量少用Vector实现类. Vector是线程不安全的, ArrayList是线程安全的.) 

14. Vector提供了一个Stack子类, 模拟"栈"结构. 常用方法: (Stack继承Vector, 所以也很老, 线程安全, 性能差, 因此较少使用. 用"栈"这种数据结构可考虑LinkedList.) 
  1. Object peek(): 返回"栈"的第一个元素, 但并不将该元素"pop"出栈. 
  2. Object pop(): 返回第一个元素, 并"pop". 
  3. void push(Object item): 讲一个元素"push"进栈. 
15. 一个用于操作数组的工具类Arrays里有个内部类也叫ArrayList, Arrays.ArrayList是一个固定长度的List集合, 只能遍历, 不能增删. 

16. Queue用于模拟"队列"这种数据结构, 先进先出(FIFO). 新元素插入(offer)到队列的尾部, 访问元素(poll)操作返回队列头部的元素. 通常不允许随机访问队列中的元素. 
  1. Queue接口常用的方法:
    - void add(Object e): 将指定元素加入此队列尾部. 
    - Object element(): 获取队头元素, 不删除. 
    - boolean offer(Object e): 将指定元素加入队尾. (当使用有容量限制的队列时, 此方法通常比add(Object e)好.) 
    - Object peek(): 获取队头元素, 不删除. 如果队列为空, 返回null. 
    - Object poll(): 获取队头元素, 并删除. 为空, 返null. 
    - Object remove(): 获取队头元素, 并删除. 
  2. Queue接口有个PriorityQueue实现类. Queue还有个Deque接口, 代表"双端队列", 双端队列可以同时从两端增删元素, 因此它的实现类即可当成队列也可当成栈(Java为Deque提供ArrayDeque和LinkedList两个实现类). 
17. PriorityQueue是个不标准的队列实现. 因为PriorityQueue保存队列元素的顺序是按队列元素大小重新排列的, 不符合FIFO. 
  1. PriorityQueue不允许插入null元素.
  2. 排序方式有自然排序和定制排序. (和TreeSet差不多.)
18. Deque是Queue的子接口. 常用方法:
  1. void addFirst(Object e): 把e插入队列开头.
    - void addLast(Object e)
  2. Iterator descendingIterator(): 返回该双端队列对应的迭代器, 以逆向顺序迭代队列中的元素. 
  3. Object getFirst(): 获取第一个元素, 不删除.
    - Object removeFirst(): 获取并删除第一个元素.
    - Object getLast()
    - Object removeLast()
  4. Object removeFirstOccurrence(Object o): 删除该双端队列第一次出现的元素o. 
    - Object removeLastOccurrence(Object o) 
  5. boolean offerFirst(Object e): 把e插入队列开头.
    - boolean offerFirst(Object e)
  6. Object peekFirst(): 获取第一个元素, 不删.  若Deque为空, 返回null.
    - Object peekLast()
  7. Object pollFirst(): 获取第一个元素, 删. 空, 返null.
    - Object pollLast()
  8. Object pop(): pop出该双端队列所表示的栈的栈顶元素, 相等于removeFirst(). 
  9. void push(Object e): 把e这个元素push进该双端队列所表示的栈的栈定, 相当于addFirst(e). 
  10. Object removeFirst(): 获取并删除
19. ArrayDeque是Deque接口的实现类. (创建时可以指定numElements参数, 用于指定Object[]数组的长度; 不指定的话, 长16.)

20. LinkedList是List和Deque接口的实现类. 

21. Map 保存映射关系的数据. key不能重复.  
  1. * Java源码是先实现了Map, 然后通过包装一个所有value窦唯null的Map实现的Set集合. (所以就是他们很像.)
  2. 常用方法: 
    - void clear()
    - Set entry Set(): 返回Map中包含的key-value对所组成的Set集合, 每个集合元素都是Map.Entry(Entry是Map的内部类)对象. 
    - Set keySet(): 返回Map中所有key组成的Set集合. 
    - Object put(Object key, Object value): 添加(or更新)一个键值对. 
    - void putAll(Map m)
    - int size(): 键值对个数. 
    - Collection values(): Map里所有value组成的Collection. 
  3. HashMap和Hashtable是Map接口的实现类, 存取对象时, 判定两个key相等必须equals()返回true, 且hashCode值相等.  判定value只需equals()返true. 
  4. LinkedHashMap是HashMap的子类, 使用双向链表来维护key-value对的次序, 该链表负责维护Map的迭代顺序(与键值对插入顺序一致), 
  5. Properties是Hashtable的子类, 用于处理属性文件(Windows上的ini文件就是一属性文件).  ----> 属性名: 属性值.
  6. 与Set接口类似, Map有SortedMap子接口, SortedMap有个TreeMap实现类. 

22. hash: hash表里可以储存元素的位置叫"桶(bucket)", 通常一桶存一个元素 ,此时性能最佳: hash算法可以根据hashCode值算出桶的存储位置, 然后从同种取出元素. 但hash表的状态为open: 在发生"hash冲突"时, 单个桶会存储多个元素, 这些元素以链表形式存储, 必须按顺序搜索. HashSet和HashMap的hash表有一下属性:
  1. 容量(capacity): 桶数. 
  2. 尺寸(size): 表中当前记录的数量. 
  3. 负载因子(load factor): 等于size/capacity. (负载因子为0表示空的hash表, 0.5表示半满的散列表, 以此类推.) 轻负载的散列表冲突少、适宜插入和查询.
  4. 初始化容量(initial capacity): 创建hash表时桶的数量。
  5. 此外, hash表里还有一个"负载极限", 是一个0~1的数值, 决定了hash表的最大填满程度(当负载因子达到负载极限时, hash会自动成倍的增加容量(桶数), 并将原有对象重新分配, 称为"rehashing"). 
23. Java提供了一个操作Set、List和Map等集合的工具类: Collections, 该工具类提供了大量方法对集合元素进行排序、查询和修改等操作, 还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法. 
  1. 排序(对List):
    - static void reverse(List list): 反转. 
    - static void shuffle(List list): 随机排序. (shuffle 方法模拟了"洗牌"动作.  --> * 所以那些播放器里的shuffle和repeat不同在于shuffle播放时随机但不重复(就只是洗乱顺序). )
    - static void sort(List list): 根据元素的自然顺序对指定List集合的元素按升序排序. 
    - static void swap(List lit, int i, int j): 交换List的i处和j处元素. 
    - static void rotate(List list, int distance): distance为正时, 将所有元素整体向后平移distance个单位, 末尾的元素循环到list头; distance为负时, 向前平移. 
  2. 查找和替换.
  3. 同步控制: Collections类中提供了多个synchronizedXxx()方法, 将指定集合包装称线程同步的集合, 从而解决多线程并发访问集合时的线程安全问题. (集合框架中常用的实现类HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和TreeMap都是线程不安全的.  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值