目录
Java编程思想(一)第1~4章:概述
Java编程思想(二)第5章:初始化和清理
Java编程思想(三)第6章:访问权限
Java编程思想(四)第7章:复用类
Java编程思想(五)第8章:多态
Java编程思想(六)第9章:接口
Java编程思想(七)第10章:内部类
Java编程思想(八)第11章:持有对象
Java编程思想(九)第12章:异常
Java编程思想(十)第13章:字符串
Java编程思想(十一)第14章:类型信息
Java编程思想(十二)第15章:泛型
Java编程思想(十三)第16章:数组
Java编程思想(十四)第17章:深入研究容器
第十七章、容器的深入研究
1. 完整的容器分类法
Java SE5新添加了:
- Queue接口:LinkedList已经为实现该接口做了修改;及其实现PriorityQueue和各种风格的BlockingQueue(用于生产者-消费者模型,多线程机制);
- ConcurrentMap接口及其实现ConcurrentHashMap,用于多线程机制;
- CopyOnWriteArrayList和CopyOnWriteArraySet,用于多线程机制;
- EnumSet和EnumMap,为使用enum而设计的set和map的特殊实现;
- 在Collections类中的多个便利方法。
2. 填充容器
Collections类也有一些实用的static方法,其中包括fill(),同Arrays一样只复制同一对象引用来填充整个容器的,并且只对List对象有用,但是所产生的列表可以传递给构造器或addAll方法。
- Collections.addAll() 将一些元素添加到一个Collection中
- Collections.nCopies() 复制一些元素到Collections中,返回一个List集合
- Collections.fill() 复制元素填充到集合当中
3. 使用Abstract类
每个java.util容器都有其自己的Abstract类,它们提供了该容器的部分实现,因此必须做的只是去实现那些产生想要的容器所必需的方法。
- AbstractList 实现了List接口;
- AbstractMap 实现了Map接口;
- AbstractSet 实现了Set接口;
享元模式(GoF23):可在普通解决方案需要过多对象,或者产生普通对象太占用空间时使用享元。享元模式使得对象的一部分可以被具体化,因此,与对象中的所有事物都包含在对象内部不同,可以在更加高效的外部表中查找对象的一部分或整体。
4.Collection的功能方法(Collection是一个接口)
下面表格列出了可以通过Collection执行的所有操作。它们也可以是通过Set或者List执行的所有操作。
Iterator迭代器接口方法:
- hasNext(); 判断是否存在下一个对象元素;
- next(); 获取下一个元素;
- remove(); 移除元素。
4. 可选操作
- 概念:执行各种不同的添加和移除的方法在Collection接口中都是可选操作。这意味着实现类并不需要为这些方法提供功能定义。
- 声明调用某些方法将不会执行有意义的行为,相反,它们会抛出异常。如果一个操作是可选的,编译器仍旧会严格要求你只能调用该接口中的方法。
- 设计原因:可以防止在设计中出现接口爆炸的情况。
4.1 未获支持的操作
- 未获支持操作异常:UnsupportedOperationException:必须是一种罕见的事件。即,对于大多数类来说,所有的操作都应该是可以工作的,只有在特例中才会有未获得支持的操作。在Java容器类库中确实如此,因为只有99%的时间里面使用的所有的容器类,如ArrayList、LinkedList、HashSet和HashMap,以及其他具体的实现,都支持所有的操作。
- 如果一个操作是未获支持的,那么在实现接口的时候就可能会导致UnsupportedOperationException异常(表明此为编程错误)。
异常案例1(Arrays.asList()):
- Arrays.asList():将数组转换为List时,产生固定尺寸的List,仅支持那些不会改变数组大小的操作。
- 最常见的未获支持的操作,源于背后由固定尺寸的数据结构支持的容器。
- 任何会引起对底层数据结构的尺寸进行修改的方法都会产生一个UnsupportedOperationException异常,以表示对未获支持操作的调用。
- 支持对容器的元素进行修改。
异常案例2(Collections.unmodifiableList()):
- Collections.unmodifiableList():产生不可修改的列表。
- 不支持对容器的元素进行修改。
5. List的功能方法
List接口:
- get(int); 获取指定索引位置的列表元素
- set(int,E); 设置指定索引位置的列表元素
- add(int,E); 将指定的元素添加到此列表的索引位置。
- remove(int); 移除指定索引位置的元素;
- indexOf(Object); 从列表头部查找Object对象元素
- lastIndexOf(Objcet); 从列表尾部查找Object对象元素
- listIterator(); 返回列表迭代器
- listIterator(int); 返回指定索引位置的列表迭代器
- subList(int,int); 该方法返回的是父list一个视图,从fromIndex(包含),到toIndex(不包含)
ListIterator迭代器接口方法:
- hasPrevious(); 如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false
- previous(); 返回列表中ListIterator指向位置前面的元素
- set(E); 从列表中将next()或previous()返回的最后一个元素返回的最后一个元素更改为指定元素e
- add(E); 将指定的元素插入列表,插入位置为迭代器当前位置之前
- nextIndex(); 返回列表中ListIterator所需位置后面元素的索引
- previousIndex(); 返回列表中ListIterator所需位置前面元素的索引
6. Set和存储顺序
- Set接口:继承来自Collection接口的行为。
- 存储顺序:不同的set实现不仅具有不同的行为,而且它们对于可以在特定的set中放置元素的类型也有不同的要求。
- default:如果没有其他限制,应该默认选择HashSet(加*),因为它对速度进行了优化。
- equals():必须为散列存储(Hash)和树形(Tree)储存都创建equals方法;
- hashCode():只有在类被置于HashSet和LinkedHashSet时才必须(即TreeSet在语法上非强制要求)。但是良好的编程风格(Effective Java)要求:覆盖equals方法时,总是同时覆盖hashCode方法。
6.1 SortedSet
SortedSet中的元素可以保证处于排序状态,SortedSet接口中的下列方法提供附加的功能:
- Comparator comparator()返回当前Set使用的Comparator;或者返回null,表示以自然方式排序。
- Object first()返回容器中的第一个元素。
- Object last()返回容器中的最末一个元素。
- SortedSet subSet(fromElement, toElement)生成此Set的子集,范围从fromElement(包含)到toElement(不包含)。
- SortedSet headSet(toElement)生成此Set的子集,由小于toElement的元素组成
- SortedSet tailSet(fromElement)生成此Set的子集,由大于或等于fromElement的元素组成
7. Queue
Queue接口包含:
- boolean add(E e); 添加一个元素,添加失败时会抛出异常
- boolean offer(E e); 添加一个元素,通过返回值判断是否添加成功
- E remove(); 移除一个元素,删除失败时会抛出异常
- E poll(); 移除一个元素,返回移除的元素
- E element(); 在队列的头部查询元素,如果队列为空,抛出异常
- E peek(); 在队列的头部查询元素,如果队列为空,返回null
- Queue在Java SE5中仅有的两个实现是LinkedList和PriorityQueue,它们的差异在于排序行为而不是性能
7.1 优先级队列
PriorityQueue:
- 设计:列表中的每个对象都包含一个字符串和一个主要的以及次要的优先级值。
- 优先级排序:该列表的排序顺序也是通过实现Comparable而进行控制的:Queue<String> queue=new PriorityQueue<>();
7.2 双向队列
- 概念:双向队列就像一个队列,但是可以在任意一段添加或移除元素。
- 实现:在LinkedList中包含支持双向队列的方法,但在Java标准类库中没有任何显式的用于双向队列的接口。因此,LinkedList无法去实现这样的接口,无法像前面转型到Queue那样向上转型为Deque。但是可以使用组合创建一个Deque类,并直接从LinkedList中暴露相关方法。
LinkedList中支持双向队列操作的相关方法:
- queue.addFirst(); 向队列首部添加元素
- queue.addList(); 向队列尾部添加元素
- queue.getLast(); 获取队列尾部元素
- queue.getFirst(); 获取队列首部元素
- queue.removeFirst(); 移除队列首部元素
- queue.removeLast(); 移除队列尾元素
- queue.size(); 返回队列大小
8. 理解Map
Map接口:
- size(); 返回Map大小
- isEmpty(); 判断Map集合是否为空
- containsKey(); 判断Mpa集合是否包括Key键
- containsVaule(); 判断Map集合是否包括Vaule
- get(Object); 获得Map集合键为Object的Vaule
- put(K,V); 添加一个K,V键值对
- remove(Object); 移除K键值对
- putAll(Map); 添加所有元素Map集合
- clear(); 清空Map中所有集合元素
- keySet(); 返回键Key的Set集合
- values(); 返回值Vaule的Set集合
- entrySet(); 返回Map.entrySet集合
- remove(Objcet,Object); 移除K,V集合
- replace(K,V,V); 替换键值对