Java容器类类库
参考文献:《Java编程思想Thinking in Java第四版》 Bruce Eckel著 机械工业出版社 P216-245
目录:
1、Java容器类类库介绍:
2、List<People> list = new ArrayList<People>()的原因:
3、容器类类库中一些常用的类或接口及其中常用的方法:
4、注意事项:
5、Iterator迭代器:
6、测试Random类的随机性:
7、Queue学习:
8、Iterable接口:
9、总结:
1、Java容器类类库介绍:
答:Java容器类类库的作用是“保存对象”(对象的引用)并将其划分为两个不同的概念:
(1)Collection:一个独立元素的序列。这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素。Set不能有重复元素。Queue按照排队规则来确定对象的产生顺序(通常与它们被插入的顺序相同)。
(2)Collection接口概括了序列的概念——一种存放一组对象的方式。
(3)Map:一组成对的“键值对”对象。映射表(关联数组,字典)将一个对象与另一个对象关联在了一起。
2、List<People> list = new ArrayList<People>()的原因:
答:ArrayList已经被向上转型为List,使用接口的目的在于如果需要去修改实现时,所需的只是在创建时修改它。比如修改为List<People> list = new LinkedList<People>();。因此,应该创建一个具体类的对象,将其转型为相应的接口,然后在其余的代码中都使用这个接口。
使用父类引用指向子类对象,再调用某一父类中的方法时,不同子类会表现出不同效果。这样的作用是扩展性极好,表现出多态,同时可维护性也很好。
3、容器类类库中一些常用的类或接口及其中常用的方法:
答:(1)Arrays:此类包含用来操作数组(比如排序和搜索)的各种方法。
①List<T> Arrays.asList():该方法接受一个数组或者是一个用逗号分隔的元素列表。
(2)Collections:此类完全在collection进行操作或返回collection的静态方法组成。
①boolean Collections.addAll():接受一个Collection对象,一个数组或者是一个用逗号分隔的列表,将元素添加到Collection中。
(3)List接口:有序的collection,也称为序列。此接口可以对列表中的每个元素的插入位置进行精确的控制。
①boolean List.add():向列表的尾部添加指定的元素。
②E List.set(int index, E element):用指定元素替换列表中指定位置的元素。index从0开始。
(4)ArrayList:List接口的大小可变数组的实现。
①boolean ArrayList.contains(Object o):如果此列表中包含指定的元素,则返回ture。
②E ArrayList.remove(int index):移除此列表中指定位置上的元素。
(5)示例代码:
package com.remoa.collectionLearn;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class AddGroups {
public static void main(String[] args) {
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));
System.out.println("collection的值:" + collection);
Integer[] moreInts = {6,7,8,9,10};
collection.addAll(collection);
System.out.println("addAll colleciton后collection的值:" + collection);
Collections.addAll(collection, 11,12,13,14,15);
System.out.println("addAll 11,12,13,14,15后collection的值:" + collection);
Collections.addAll(collection, moreInts);
System.out.println("addAll moreInts后collection的值:" + collection);
List<Integer> list = Arrays.asList(16,17,18,19,20);
System.out.println("list的值" + list);
list.set(1, 100);
System.out.println("set后list的值" + list);
list.add(25);
System.out.println("add后list的值" + list);
}
}
运行结果:
图3.1 运行结果
最后报“不支持的操作”的异常,是因为Array.asList的底层表示的是数组,不能调整尺寸。当使用add或delete操作时,就可能会引发改变数组尺寸的尝试,则会报异常。
4、注意事项:
答:(1)在默认的打印行为中,Collection打印出来的内容用方括号括住,每个元素由逗号分隔。Map则用大括号括住,键与值由等号联系。
(2)HashMap提供了最快的查找技术,也没有按照任何明显的顺序来保存其元素;TreeMap按照比较结果的升序保存键;LinkedHashMap按照插入顺序保存键,同时还保留了HashMap的查询速度。
(3)ArrayList擅长随机访问元素,但是在List的中间插入和移除元素时较慢。LinkedList通过较低代价在List中间进行插入和删除操作,提供了优化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。
5、Iterator迭代器:
答:迭代器的工作是遍历并选择序列中的对象。
(1)使用过程:
①使用方法iterator()要求容器返回一个Iterator。Iterator将准备好返回序列中的第一个元素。
②使用next()获得序列中的下一个元素。
③使用hashNext()检查序列中是否还有元素。
④使用remove()将迭代器新近返回的元素删除。
6、测试Random类的随机性:
(1)示例代码:RandomTest.java
package com.remoa.collectionLearn;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
Random ran = new Random();
Map<Integer, Integer> map = new HashMap<Integer,Integer>();
for(int i = 0; i < 10000; i++){
int r = ran.nextInt(20);
Integer freq = map.get(r);
map.put(r, freq == null ? 1 : freq + 1);
}
System.out.println(map);
}
}
(2)运行结果:
图6.1 运行结果
7、Queue学习:
答:队列是一个先进先出的容器。常被当做一种可靠的将对象从程序的某个区域传输到另一个区域的途径。队列在并发编程中特别重要,因为它们可以安全地将对象从一个任务传输给另一个任务。
(1)offer()方法:在允许的情况下,将一个元素插到队尾。
(2)element()方法:在不移除的情况下获取队头,且在队列为空时抛出NoSuchElementException异常。
(3)peek()方法:在不移除的情况下获取队头,在队列为空时返回null
(4)poll()方法:移除并获取队头,在队列为空时返回null
(5)remove()方法:移除并获取队头,且在队列为空时抛出NoSuchElementException异常。
示例代码:QueueDemo.java
package com.remoa.collectionLearn;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class QueueDemo {
public static void printQ(Queue queue){
while(queue.peek() != null){
System.out.print(queue.remove() + " ");
}
System.out.println();
}
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<Integer>();
Random r = new Random();
for(int i = 1; i < 10; i++){
queue.offer(r.nextInt(i + 10));
}
printQ(queue);
Queue<Character> qc = new LinkedList<Character>();
for(char c : "Remoa is a student".toCharArray()){
qc.offer(c);
}
System.out.println(qc.element());//获取队列的头
printQ(qc);
}
}
运行结果:
图7.1 运行结果
8、Iterable接口:
答:示例代码:Iter.java
package com.remoa.collectionLearn;
import java.util.Iterator;
public class Iter implements Iterable<String>{
protected String[] words = ("We are a group of juniors that have dreams in college.").split(" ");
@Override
public Iterator<String> iterator() {
return new Iterator<String>(){
private int index = 0;
@Override
public boolean hasNext() {
return index < words.length;
}
@Override
public String next() {
return words[index++];
}
};
}
public static void main(String[] args) {
for(String s : new Iter()){
System.out.print(s + " ");
}
}
}
运行结果:
图8.1 运行结果
iterator()方法返回的是实现了Iterator<String>的匿名内部类的实例,该匿名内部类可以遍历数组中的所有单词。在main函数中可以看到Iter类确实可以用在foreach语句中。
9、总结:
答:(1)数组将数字和对象联系起来。它保存类型明确的对象,查询对象时,不需要对结果做类型转换。它可以是多维的,可以保存基本类型的数据。数组一旦生成,其容量就不可以改变。
(2)各种Collection和各种Map都可以在向其中添加更多的元素时,自动调整其尺寸大小。容器不能持有基本类型,但是自动包装机制会仔细地执行基本类型到容器中所持有的包装器类型之间的双向转换。
(3)如果要进行大量的随机访问,就要使用ArrayList;如果要经常从表中间插入或删除元素,则应该使用LinkedList。
(4)新程序中不应该使用过时的Vector,Hashtable和Stack。