Java编程思想之持有对象

来源:互联网 发布:mac ipython 编辑:程序博客网 时间:2024/06/05 15:55
  • 通常,程序总是根据运行时才知道的某些条件去创建新对象。在此之前,不会知道所需对象的数量,甚至不知道确切的类型。为了解决这个普遍的编程问题,需要在任意时刻和任意位置创建任意数量的对象,所以,就不能依靠创建命名的引用来持有每一个对象:
    MyType.aReference;
    因为你不知道实际上会需要多少这样的引用。
    使用数组和容器类来解决这个问题。

1 基本概念

Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
1. Collection。一个独立的元素序列。List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。
2. Map。一组成对的“键值对”对象,允许使用键来查找值。映射表允许我们使用另一个对象来查找某个对象,它也被称为“关联数组”。
在理想情况下,编写的大部分代码都是在与这些接口打交道,并且唯一需要指定所使用的精确类型的地方就是在创建的时候。因此,可以像这样创建一个List:

List<Apple> apples = new ArrayList<Apple>();    //ArrayList已被向上转型为List。

应该创建一个具体类的对象,将其转型为对应的接口,然后在其余的代码中都使用这个接口。

2 Foreach与迭代器

迭代器是一个对象,它的工作是遍历并选择序列中的对象。
Java的迭代器只能单向移动,这个Iterator只能用来:
1. 使用方法iterator()要求容器返回一个Iterator,Iterator将准备好返回序列的第一个元素。
2. 使用next()获得序列中的下一个元素。
3. 使用hasNext()检查序列中是否还有元素。
4. 使用remove()将迭代器最近返回的元素删除。
迭代器统一了对容器的访问方式。
foreach语法主要用于数组,但是它也可以应用于任何Collection对象。Collection 之所以能够与foreach 一起工作,是因为Java SE5 引入了新的被称为 Iterable的接口,该接口包含一个能够产生 Iterator的 iterator()方法,并且 Iterable接口被 foreach用来在序列中移动。因此创建了任何实现 Iterable的类,都可以将它用于 foreach语句中。
数组并不是 Iterable的。

2.1 ListIterator

是一个更加强大的 Iterator的子类型,它只能用于各种List类的访问。ListIterator 可以双向移动。它还有产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引,并且可以用 set()方法替换它访问过的最后一个元素。

import java.util.*;class Student{    private String name;    public Student(String name){        this.name = name;    }    public String toString(){        return name;    }}public class ListIteration{    public static void main(String[] args){        List<Student> stu = new ArrayList<Student>();        stu.add(new Student("a"));        stu.add(new Student("b"));        stu.add(new Student("c"));        ListIterator<Student> it = stu.listIterator();        while(it.hasNext()){            System.out.println(it.next()+" , "+it.nextIndex()+" , "+it.previousIndex()+";");                }        //System.out.println();        System.out.println(stu);        it = stu.listIterator(1);        while(it.hasNext()){            it.next();            it.set(new Student("dd"));        }        System.out.println(stu);    }}/*运行结果为:a , 1 , 0;  //注意it.previousIndex()方法返回的是“以前的”索引,即当前元素的索引值b , 2 , 1;c , 3 , 2;[a, b, c][a, dd, dd]*/

3 LinkedList

它执行某些操作(在 List的中间插入和移除)时比ArrayList更高效,但在随机访问操作方面却要逊色一些。
LinkedList 还添加了可以使其用作栈、队列或双端队列的方法。

4 Stack

“栈”通常是指”后进先出”(LIFO)的容器。
LinkedList具有能够直接实现栈的所有功能的方法。

/*使用LinkedList实现Stack*/public class Stack<T>{    private LinkedList<T> storage = new LinkedList<T>();    public void push(T v){ storage.addFirst(v);}    public T peek(){ storage.getFirst();}    public T pop(){ storage.removeFirst();}    public boolean empty(){ return storage.isEmpty();}    public String toString(){ return storage.toString();}}

5 Set

Set不保存重复元素,Set中最常被使用的是测试归属性,你可以很容易地询问某个对象是否在某个Set中。
TreeSet 将元素存储在红-黑树数据结构中,而 HashSet使用的是散列函数。LinkedHashSet 因为查询速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。

原创粉丝点击