您的位置:首页 > 编程语言 > Java开发

java编程思想读书笔记 第十一章 持有对象(总结)

2016-10-08 22:26 260 查看
1.Collection和Iterator

Collection是描述所有序列容器的共性的根接口,它可能会本认为是一个“附属接口”,即因为要表示其他若干个接口的共性而出现的接口。另外,java.util.AbstractCollection类提供了Collection的默认实现,使得你可以创建一个AbstractCollection的子类时,而其没有不必要的代码重复。

使用接口描述的一个理由是它可以使我们能创建更通用的代码。通过针对接口而非具体实现来编写代码,我们的代码可以应用于更多的对象类型。因此,如果我编写的方法将接受一个Collection接口,那么该方法就可以应用于任何实现了Collection的类–这也就使得一个新类可以选择去实现Colle接口,以便我的方法可以使用它。

2.Foreach和迭代器

Foreach的用法主要用于数组,但是它也可以用于任何的Collection对象。例如:

public class ForEachCollections {

public static void main(String[] args) {
Collection<String> cs = new LinkedList<String>();
Collections.addAll(cs, "Take the long way home".split(" "));
for (String s : cs) {
System.out.print("'"+s+"'");
}
}


}

输出:’Take”the”long”way”home’

由于cs是一个Collec,所以这段代码展示了能够与foreach一起工作是所有Collection对象的特性。之所以能够工作,是因为javaSe5引入了新的被称为Iterable的接口,该接口包含一个能够产生Iterator的iterator()方法。,并且Iterable接口被foreach用来在系列中移动。因此如果你创建了任何实现Iterable的类,都可以将它用于foreach语句中:

public class IterableClass implements Iterable<String>{
protected String[] words ="And that is how we konw the Earth to be banana-shaped.".split(" ");
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return index < words.length;
}
@Override
public String next() {
// TODO Auto-generated method stub
return words[index++];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
for (String s : new IterableClass()) {
System.out.print(s + " ");
}
}
}


iterator()方法返回的是实现了Iterable的匿名内部类的实例,该匿名内部类可以遍历数组的所有单词。在main()中,你可以看到IterableClass 确实可以用于foreach语句中。

在javaSE中,大量的类都是Iterable类型,主要包括所有的Collection类(但是不包括各种Map)。例如,下面的代码可以显示所有的操作系统的环境变量:

public class EnviromentVariable {

public static void main(String[] args) {
for (Map.Entry entry : System.getenv().entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}


System.getenv()返回一个Map,.entrySet()产生一个由Map.Entry的元素构成的Set,并且这个Set是一个Iterable,因此可以用于foreach循环。

foreach语句可以用于数组或其他任何Iterable,但是这并不意味着数组肯定也会死一个Iterable,而且任何自动包装也不会自动发生:

public class ArrayIsNotIterable {
static<T> void test (Iterable<T> ib){
for (T t : ib) {
System.out.println(t+" ");
}
}
public static void main(String[] args) {
test(Arrays.asList(1,2,3));
String[] strings = {"A","B","C"};
test(Arrays.asList(strings));
}
}


尝试把数组当作一个Iterable参数传递会导致失败。这说明不存在任何从数组到Iterable的自动转换,你必须手工执行这种转换。

3.总结

java提供了大量持有对象的方式:

1)数组将数字与对象联系起来。它保存类型明确的对象,查询对象时,不需要对结果做类型转换。它可以是多维的,可以保存基本类型的数据。但是,数组一旦生成,其容量就不能改变。

2)Collection保存单一的元素,而Map保存相关联的键值对。有了Java的泛型,你就可以指定容器中存放的对象类型,因此你就不会将错误的类型的对象放置到容器中,并且在容器中获取元素时,不必进行类型的转换。各种Collection和各种Map都可以在你向其中添加更多的元素时,自动调整其尺寸。容器不能持有基本类型,但是自动包装机制会仔细地执行基本类型到容器中所持有的包装类型之间的双向转换。

3)像数组一样,List也建立数字索引与对象的关联,因此,数组和List都是排序好的容器。List能够自动扩充容量。

4)如果要进行大量的随机访问,就使用ArrayList,如果要经常从表中间插入或删除元素,则应该使用LinkedList。

5)各种Queue以及栈的行为,由LinkedList提供支持。

6)Map是一种对象(而非数字)与对象相关联的设计。HashMap设计用来快速访问;而TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问能力。

7)Set不接受重复元素。HashSet提供最快的查询速度,而TreeSet保持元素处于排序的状态。LinkedHashSet以插入顺序保存元素。

8)新程序中不应该使用过时的Vector、HashTable和Satck。

java容器的简图如下图所示:



你可以看到,其实只有四种容器:Map、List、Set和Queue,它们各有两到三个实现版本,常用的容器用黑色粗线框表示。点线框表示接口,实线框表示普通的(具体的)类。带有空心箭头的点线表示一个特定的类实现了一个接口,实心箭头表示某个类可以生成箭头所指向类的对象。例如,任意的Collection可以生成Iterator,而List可以生成ListIterator(也能生成普通的Iterator,因为List继承自Collection)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息