代码改变世界

Java集合类(Java Collections classes)

2012-11-08 22:31  Justany_WhiteSnow  阅读(667)  评论(0编辑  收藏  举报

 Java集合结构图

 

 

Example1:

Problem: Want a simple banking system. Can look up accounts by name or number, deposit or withdraw, print.

问题:设计一个简单的银行系统。可以看到每一个账号里面的名称、编号、存款或取款,并打印之。

方案:

class Account {
    Account (String name, String number, int init) {
        this.name = name; this.number = number;
        this.balance = init;
    }
    /** 账号拥有者名字 */
    final String name;
    /** 账号编号 */
    final String number;
    /** 当前余额 */
    int balance;
    /** 按照一定格式打印 */
    void print (PrintWriter str) { ... }
}
class Bank {
    SortedMap<String,Account> accounts = new TreeMap<String,Account> ();
    SortedMap<String,Account> names = new TreeMap<String,Account> ();
    void openAccount (String name, int initBalance) {
        Account acc = new Account (name, chooseNumber (), initBalance);
        accounts.put (acc.number, acc);
        names.put (name, acc);
    }
    void deposit (String number, int amount) {
        Account acc = accounts.get (number);
        if (acc == null) ERROR(...);
        acc.balance += amount;
    }
    // 取款也相同
    /** 按照账号编号打印 */
    void printByAccount (PrintStream str) {
        for (Account account : accounts.values ())
            account.print (str);
    }
    /** 按照账号拥有者打印 */
    void printByName (PrintStream str) {
        for (Account account : names.values ())
           account.print (str);
    }
}

A Design Question: What would be an appropriate representation for keeping a record of all transactions (deposits and withdrawals) against each account?

一个设计问题:怎样的形式适合存储每个账号的交易(存款或者提款)数据?

 

Example2

抽象类应用例子。

Problem: Want to create a reversed view of an existing List (same elements in reverse order).

问题:如何创建一个反序列表。

public class ReverseList<Item> extends AbstractList<Item> {
    private final List<Item> L;
    public ReverseList (List<Item> L) { this.L = L; }
    public int size () { return L.size (); }
    public Item get (int k) { return L.get (L.size ()-k-1); }
    public void add (int k, Item x)
        { L.add (L.size ()-k, x); }
    public Item set (int k, Item x)
        { return L.set (L.size ()-k-1, x); }
    public Item remove (int k)
        { return L.remove (L.size () - k - 1); }
}

 

ArrayList

– Advantages: compact, fast random access (indexing).
– Disadvantages: insertion, deletion can be slow

— 好处:

  1. 紧凑的空间利用,比其包含的所有元素所占空间总量要小
  2. 随机获取元素快(Θ(1)),常数时间完成操作

— 坏处:

  在最坏情况下,改变序列的操作非常缓慢(Θ(N))

  • 考虑A.read(x),也就是A.add(A.size(), x),即在序列最后添加元素。对于一个总容量为K的ArrayList,如果当存储元素达到总容量时,总容量扩大1,则有成本:

    

于是最差情况下有:

    

有点没写清楚,应该是Θ(M0 + (M0 + 1) + ... +  (M0 + N))

  • 换一种方法,如果到达总容量时,容量扩一倍,则有成本:

    

我们利用势能分析法(potential method),构造一个势能公式,势能必然与添加元素个数i,容量Si,原容量S0有关,满足:

    ai + b (Si - S0)

必须满足,势能起点为0,势能必然大于0。所以可以构造出:

   

因为2i > Si ,所以满足大于等于0。

当i < Si 时,有:

当i = Si 时,有:

可见分摊成本是常数。

 

单链表(Singly Linked Lists)

简单实现:

class Entry {
    Entry (Object head, Entry next) {
        this.head = head; this.next = next;
    }
    Object head;
    Entry next;
}

Changing the structure of a linked list (its set of containers) involves what is colloquially known as “pointer swinging.” 

改变其数据结构,要使用被俗称为“摇曳的指针”(正如你所见到的,这是我胡起的)的手段。

“哨兵”(Sentinels)技术:

通常我们用这种方式添加链表:

L = L.next; 
L = new Entry ("aardvark", L); 

但这样子头部的时候有所差别,所以我们添加一个“哨兵”节点来解决头部的差异性:

然后我们这要返回除掉哨兵节点的链表就可以了。

单链表好处:

  • 简单创建,操作方便

单链表坏处:

  1. 被迫只能从头部迭代到当前位置,没有较快的方法到当前位置
  2. 要删除当前位置的元素,我们需要前一个元素的指针,但单链表没这东东

于是我们添加一个向前的指针来解决这个问题。

 

 

特殊列表

堆栈(Stack):先进的后出,从头部进从头部出。

队列(Queue):先进的先出,从头部进从尾部出。

双端列表(Deque):那边进出都可以。

 

相关资料

Data Structures (Into Java) . Paul N. Hilfinger

Potential method . Wiki

数据结构(算法艺术) . 刘汝佳