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

来源:互联网 发布:淘宝男装店铺名称 编辑:程序博客网 时间:2024/06/04 18:14

1.Set
Set不保存重复的元素。如果你将相同的对象的多个实例添加到Set中,那么它就会阻止这种重复现象。Set中最常被使用的是测试归属性,你可以很容易地询问某个对象是否在某个Set中。正因如此,查找就成为了Set中最重要的操作,因此你通常都会选择一个HashSet的实现,它专门对快速查找进行了优化。Set和Collection完全一样的接口,因此没有任何额外的功能,不像前面两个不同的List。实际上Set就是Collection,只是行为不同。而HashSet所维护的顺序与TreeSet或LinkedHashSet都不同,因为他们的实现具有不同的元素存储方式。TreeSet将元素存储在红-黑树数据结构中,而HashSet使用的是散列函数。LinkedHashList因为查询速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。如果想对结果排序,一种方式就是使用TreeSet来代替HashSet。

2.Map
将对象映射到其他对象的能力是一种解决编程问题的杀手锏。例如,考虑一个程序,它将用来检查java的Random类的随机性。理想状态下,Random可以将产生的理想的数字分别,但要想测试它,则要生成大量的随机数,并对落入各种不同范围的数字进行计数。Map可以很容易地解决该问题。在本例中,键是由Random产生的数字,而值是该数字出现的次数:

public class Satatistics {    public static void main(String[] args) {        Random rand = new Random(47);        Map<Integer, Integer> map = new HashMap<Integer, Integer>();        for (int i = 0; i < 10000; i++) {            int r = rand.nextInt(20);            Integer freq = map.get(r);            map.put(r, freq == null ? 1: freq + 1);        }        System.out.println(map);    }}

在main()中,自动包装机制将随机生成的int转换为HashMap可以使用Integer的引用(不能使用基本类型的容器)。如果键不在容器中,get()方法将返回null(这表示第一次被找到),否则,get()方法将产生与该键相关联的Integer值,然后这个值被递增(自动包装机制再次简化了表达式,但是确实发生了对Integer的包装和拆包)。在Map中可以使用containsKey和containsValue来查看是否包含某个键或某个值。Map与数组和其他的Collection一样,可以很容易地扩展到多维,而我们只需将其值设为Map(这些Map的值可以是其他容器,甚至是其他Map)。因此,我们能够很容易地将容器组合起来从而快速地生成强大的数据结构。

3.Queue
队列是一个典型的先进先出的容器。即从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序相同。队列常被当作一种可靠的将对象从程序的某个区域传输到另一个区域的途径。
LinkedList提供了方法以支持队列行为,并且它实现了Queue接口,因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue,下面的例子使用了在Queue接口中与Queue接口中与Queue相关的方法:

public class QueueDemo {    public static void printQ(Queue queue){        while(queue.peek() != null){            System.out.print(queue.remove()+ " ");        }    }    public static void main(String[] args) {        Queue<Integer> queue = new LinkedList<Integer>();        Random random = new Random(47);        for (int i = 0; i < 10; i++) {            queue.offer(random.nextInt(i + 10));        }        printQ(queue);        Queue<Character> qcCharacters = new LinkedList<Character>();        for (char c : qcCharacters) {            qcCharacters.offer(c);        }        printQ(qcCharacters);    }}输出:8 1 1 1 5 14 3 1 0 1 

offer()方法使与Queue相关的方法之一,它在允许的情况下,将一个元素插入到队尾,或者返回false。peek()和element()都将在不移除的情况下返回对头,但是peek()方法在队列为空时返回null,而element()会抛出NoSuchElementException异常。poll()和remove()方法将移除并返回对头,但是poll()在队列为空时返回null,而remove()会抛出NoSuchElementException异常。自动包装机制将会自动地将nextIn()方法的int结果转换为queue所需的Integer对象,将char c 转换为qcCharacters 所需的Character对象。Queue接口窄化了对LinkedList的方法的访问权限,以使得只有恰当的方法才可以使用,因此,你能够访问的LinkedList的方法会变少。注意Queue相关的方法提供了完整而独立的功能。即,对于Queue所继承的Collection,在不需要使用它的任何方法的情况下,就可以拥有一个可用的Queue。

4.PriorityQueue
先进先出描述的是最典型的队列规则。队列规则是指在给定一组队列的元素的情况下,确定下一个弹出队列的元素的规则。先进先出声明的是下一个元素应该是等待时间最长的元素。优先级队列声明下一个弹出元素时最需要的元素(具有最高的优先级)。当你再PriorityQueue上调用offer()方法来插入一个对象时,这个对象会在队列中被排序。默认的排序将使用对象在队列中的自然顺序,但是你可以通过提供自己的Comparator来修改这个顺序。PriorityQueue可以确保当你调用peek()、poll()和remove()方法时,获取的元素将时队列中优先级最高的元素。在PriorityQueue中,重复是允许的。如果你想在PriorityQueue中使用自己的类,就必须包括额外的功能以产生自然排序,或者提供自己的Comparator。

0 0
原创粉丝点击