博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java编程思想第四版第十一章总结
阅读量:5095 次
发布时间:2019-06-13

本文共 13617 字,大约阅读时间需要 45 分钟。

1. 容器类被分为两类:Collection和Map

  • Collection是一个接口:包括:
    • List接口:
      • ArrayList:按照被插入顺序保存元素, 查询快, 增删改慢
      • LinkedList:按照被插入顺序保存元素, 增删改块,查询慢。
    • Set接口:元素不能重复
      • HashSet:已相当复杂的方式来存储元素,这种技术是最快的获取元素的方式
      • TreeSet:按照结果的升序保存元素
        • 可以自行执行排序方式。默认是按照字典顺序排序。如果想按照字母顺序排序,可以向TreeSet构造器中传入String。CASE_INSENTIVE_ORDER.
      • LinkedHashSet:按照添加顺序保存元素
    • Queue接口
  • Map接口
    • HashMap:已相当复杂的方式来存储元素(散列函数),这种技术是最快的获取元素的方式
    • TreeMap:按照比较结果的升序保存,元素存储在红黑树数据结构。
    • LinkedHashMap:按照添加顺序保存元素。

2. 定义集合的时候,使用向上转型,是一个好的习惯

  List<Apple> list = new ArrayList<Apple>();

  注意:ArrayList已经被向上转型为List,这样做的好处是,如果你想使用其他List的实现类也是可以的。缺点是,在ArrayList中有一些额外的方法,不包含在List中,如果需要调用这些方法,还需要使用ArrayList来定义。

3. Collection集合的使用

  • 添加一组元素
    package net.mindview.holding;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Collections;import java.util.List;public class AddingGroups {    public static void main(String[] args) {        //1. Collection集合,有一个构造方法, 可以接受一个集合作为参数, 将数组内容直接作为Collections的内容.                Collection
    collection = new ArrayList
    (Arrays.asList(1,2,3,4,5)); Integer[] moreInts = {
    6, 7, 8, 9, 10}; //2. 集合有一种方法,添加一个数组为它的元素. 这种方法没有Collections.addAll高效 //原因: 第一种方式首先要初始化,然后将数组转换为集合后, 赋值. 第二种方法方法直接赋值,所以更高效 collection.addAll(Arrays.asList(moreInts)); //定义一个集合, 使用Collections.addAll()方式添加元素是一种推荐的方式.效率高 Collections.addAll(collection, 11,12,13,14,15); Collections.addAll(collection, moreInts); //将数组直接转换为list,有两点需要说明:1. 大小固定, 不能添加元素,删除元素, 可以修改. 2. 局限性,下面的代码说明. List
    list = Arrays.asList(16,17,18,19,20); list.set(1, 99); }}

    相信看上面的注释, 下面说一说Arrays.asList()的局限性.

    package net.mindview.holding;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.List;/** * 这里说的是一个间接继承和直接继承的问题 */class Snow {}class Powder extends Snow{}class Light extends Powder{}class Heavy extends Powder{}class Crusty extends Snow{}class Slush extends Snow{}public class AsListInference {    public static void main(String[] args) {        //1. 下面的定义可以通过, 他们都继承自Snow        List
    snow1 = Arrays.asList(new Powder(), new Crusty(), new Slush()); //2. 下面的定义不能通过, 因为他们都是间接继承自snow.而非直接 //List
    snow2 = Arrays.asList(new Light(), new Heavy()); //3. 上面的方式编译不通过,但是下面的却可以.为什么呢? 因为他从第一个元素了解到了此目标类型是snow List
    snow3 = new ArrayList
    (); Collections.addAll(snow3, new Light(), new Heavy()); //4. 方法2可以通过显示类型参数说明,来明确指出转换的类型 List
    snow4 = Arrays.
    asList(new Light(), new Heavy()); }}

     

  • 容器的打印
    • 数组的打印,使用Arrays.toString(数组名);
      public static void main(String[] args) {    String[]  str = new String[5];    System.out.println(str);    System.out.println(Arrays.toString(str));}

       

    • 容器的打印, 直接打印容器名, 无需任何帮助.

 4. Stack

  栈: 先进后出(LIFO),有时栈也被称为叠加栈, 因为最后“压入”的,最先弹出。

  LinkedList具有能够直接实现栈的所有功能的方法。因此可以直接将LinkedList作为栈直接使用。

  也就是说LinkedList中有方法是先进后出的。

package net.mindview.holding;import java.util.LinkedList;/** * 模拟栈 */public class Stack
{ private LinkedList
storage = new LinkedList
(); //进入 public void push(T v){ storage.addFirst(v); } public T peek(){ return storage.removeFirst(); } //取出 public T pool(){ return storage.removeFirst(); } public boolean empty(){ return storage.isEmpty(); } public String toString(){ return storage.toString(); }}

 

package net.mindview.holding;public class StackTest {        public static void main(String[] args) {        Stack
stack = new Stack
(); for(String s:"this is my dog!".split(" ")){ stack.push(s); } if(!stack.empty()){ System.out.println(stack.peek()); System.out.println(stack.pop()+" "); System.out.println(stack.pop()+" "); System.out.println(stack.peek()); } }}

运行结果:

dog!

dog!
my
is

  通过这个案例: 可以看出, 所谓的先进后出,指的是, add最后进来的, remove时最先出去. 跟排序没有任何关系.

 5. Queue 队列

  队列是一个典型的先进先出的容器. 即从容器的一段放入,从另一端取出. 并且事物放入容器的顺序与取出的顺序是相同的。

  LinkedList提供了方法以支持队列的行为。并且它实现了Queue接口。因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue,下面展示了Queue的用法。

package net.mindview.holding;import java.util.LinkedList;import java.util.Queue;import java.util.Random;public class QueueDemo {    public static void print(Queue queue){        //从队列中取元素--先放进去的,先取出来        while(queue.peek() != null){            //从队列中删除一个元素            System.out.print(queue.remove() + " ");        }        System.out.println();    }    public static void main(String[] args) {        Queue
queue = new LinkedList
(); Random rand = new Random(47); for(int i=0; i<10; i++){ //向队列里放入元素 queue.offer(rand.nextInt(i+10)); } print(queue); Queue
qc = new LinkedList
(); for(char c:"Brontosaurus".toCharArray()){ //向队列里放入元素 qc.offer(c); } print(qc); }}
8 1 1 1 5 14 3 1 0 1 B r o n t o s a u r u s

 

  • offer()方法,:在允许的情况下,将一个元素插入到队尾。或者返回false。
  • peek()和element():在不移除的情况下返回对头。但是peek方法在队列为空时,返回null。而element()会抛出NoSuchElementException异常。
  • poll()和remove():将移除并返回队头。poll在队列为空时返回null,remove在队列为空是抛出NoSuchElementException异常。

这里想Queue中放入元素使用的时offer,取出元素使用的时peek,删除元素使用的remove。先放进去的先取出来。

  我们再说到Stack时,看到LinkedList可以实现Stack先进后出。看到队列的Queue的时候, 又说LinkedList可以实现Queue先进先出。这是怎么回事呢?来看看API,原来是这么回事

6. PriorityQueue:优先级队列

  优先级队列声明,下一个弹出元素是最需要的元素。也就是说是优先级最高的元素。当你使用offer方法来出入一个对象时,这个对象会在队列中被排序。默认的顺序将使用对象在队列中的自然顺序。但你也可以通过自己的Comparator来修改这个顺序。

  PriorityQueue可以确保当你调用peek(), poll(), remove()方法时, 获取元素将是队列中优先级最高的元素.

package net.mindview.holding;import java.util.Arrays;import java.util.Collections;import java.util.HashSet;import java.util.List;import java.util.PriorityQueue;import java.util.Random;import java.util.Set;public class PriorityQueueDemo {    public static void main(String[] args) {        /*         * 对于数字而言, 最小的数字优先级最高         */        PriorityQueue
priorityQueue = new PriorityQueue
(); Random rand = new Random(47); for(int i=0;i<10;i++){ priorityQueue.offer(rand.nextInt(i+10)); } QueueDemo.print(priorityQueue); /* * 将一个list集合中的元素放入队列 * 并且使用自定的排序方式排序 */ List
ints = Arrays.asList(25, 22, 20, 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25); priorityQueue = new PriorityQueue
(ints); QueueDemo.print(priorityQueue); //提供了一个构造器, 使用自定义的排序方法.第二个参数是新的排序方法,继承了Comparator类. priorityQueue = new PriorityQueue
(ints.size(), Collections.reverseOrder()); priorityQueue.addAll(ints); QueueDemo.print(priorityQueue); /* * 字符串集合放入到优先级队列 */ String fact = "EDUCATION SHOULD ESCHEW OBFUSACTION"; List
strings = Arrays.asList(fact.split(" ")); PriorityQueue
stringPQ = new PriorityQueue
(strings); QueueDemo.print(stringPQ); /* * 使用set存储不重复的字符集合 * 最小的值有最高的优先级. 空格的优先级比字母高 */ Set
charSet = new HashSet
(); for(char c: fact.toCharArray()){ charSet.add(c); } PriorityQueue
charPQ = new PriorityQueue
(charSet); QueueDemo.print(charPQ); }}

运行结果:

0 1 1 1 1 1 3 5 8 14 1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25 25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1 EDUCATION ESCHEW OBFUSACTION SHOULD   A B C D E F H I L N O S T U W

 

  1. 数字越小,优先级越高

  2. 空格的优先级比字母高

  3. 字符串,字符都可转换为对应的数字处理.

7. Iterator 

  java中, 用迭代器Iterator而不是集合Collection来表示集合间的共性。但是, 实现了Collection就意味着需要提供Iterator()方法。 

  (未完,待完善)

8. Foreach和迭代器

  Iterable接口:该接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此,如果你创建的类实现了Iterable接口,都可以将它用于foreach语句中:

package net.mindview.holding;import java.util.Iterator;/** * Iterable 接口包含一个能够产生Iterator的iterator()方法. 并且Iterable接口被用来在foreach用来在序列中移动。 * 因此,如果你创建了任何实现Iterable的类,都可以将其用于foreach语句中。 * @author samsung * */public class IterableClass implements Iterable
{ protected String[] words = ("And that is how we know the Earth to be banana-shaped.").split(" "); @Override public Iterator
iterator() { // TODO Auto-generated method stub return new Iterator
(){ private int index = 0; @Override public boolean hasNext() { return index < words.length; } @Override public String next() { return words[index++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public static void main(String[] args) { //只要这个类实现了Iterable,就可以使用foreach语句遍历 for(String str: new IterableClass()){ System.out.println(str); } }}

运行结果

AndthatishowweknowtheEarthtobebanana-shaped.

 

9.适配器方法

  我们知道一个类如果实现了Iterable接口, 他就要重写返回Iterator类型的iterator方法,我们使用的时候,就可以使用foreach的方式来遍历这个类。但是,这种实现接口的方式,只能够有一个种遍历方法。假如:我现在想要有多种遍历方案。比如:正序遍历,反序遍历,该如何实现呢?我们使用适配器方法来实现。代码如下:

package net.mindview.holding;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Iterator;class ReversibleArrayList
extends ArrayList
{ private static final long serialVersionUID = 1L; public ReversibleArrayList(Collection
c) { super(c); } /** * 实现了一个反转, 将传递过来的集合,反向输出 */ public Iterable
reversed(){ return new Iterable
(){ @Override public Iterator
iterator() { return new Iterator
(){ int current = size()-1; @Override public boolean hasNext() { return current >= 0; } @Override public T next() { return get(current--); } @Override public void remove() { // TODO } }; } }; }}public class AdapterMethodIdiom { public static void main(String[] args) { ReversibleArrayList
r = new ReversibleArrayList(Arrays.asList("To be or not to be".split(" "))); for(String str: r){ System.out.print(str + " "); } System.out.println(); for(String str:r.reversed()){ System.out.print(str + " "); } }}

  这个例子展示了, 我在一个类中,可以定义多种foreach循环的方式。下面我们使用这种方式,为IterableClass定义两种其他的循环方式:

package net.mindview.holding;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.Random;/** * 继承了IterableClass类,就拥有了一种遍历方法了 * @author samsung * */public class MultiIteratorClass extends IterableClass{    /**     * 反序遍历     * @param args     */    public Iterable
reverse(){ return new Iterable
(){ @Override public Iterator
iterator() { return new Iterator
(){ int count = words.length-1; @Override public boolean hasNext() { return count >= 0; } @Override public String next() { return words[count--]; } @Override public void remove() { } }; } }; } /** * 随机访问遍历 * 这里没有创建自己的Iterator,而是直接返回被打乱的List中的Iterator. * 这里使用Collections.shuffle()方法并没有影响到原来的数组,这是将原来数组的元素的引用打乱了.注意,是引用打乱了. * */ public Iterable
randomized(){ return new Iterable
(){ @Override public Iterator
iterator() { List
shuffled = new ArrayList
(Arrays.asList(words)); Collections.shuffle(shuffled, new Random(47)); return shuffled.iterator(); } }; } public static void main(String[] args) { MultiIteratorClass m = new MultiIteratorClass(); for(String s:m){ System.out.print(s+" "); } System.out.println(); for(String s: m.reverse()){ System.out.print(s+" "); } System.out.println(); for(String s: m.randomized()){ System.out.print(s+" "); } }}

  这里面在说说Collection.shuffle()方法. 看下面的例子就明白了

package net.mindview.holding;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.List;import java.util.Random;public class ModifyingArraysAsList {        public static void main(String[] args) {        Random rand = new Random(47);        Integer[] ia = {
1,2,3,4,5,6,7,8,9,10}; /* * list1包装了一层 * 从结果可以看出: 如果数组转List后被包装一层,调用Collections.shuffle打乱顺序, * 打乱的是数组中元素的引用,数组的顺序没有改变 */ List
list1 = new ArrayList
(Arrays.asList(ia)); System.out.println("Before shuffling:"+list1); Collections.shuffle(list1, rand); System.out.println("After shuffling: "+list1); System.out.println("array: "+Arrays.toString(ia)); /* * list2没有包装 * 从结果可以看出: 如果数组转List后没有包装,调用Collections.shuffle打乱顺序,打乱的是数组中元素的顺序 */ List
list2 = Arrays.asList(ia); System.out.println("Before shuffling:"+list2); Collections.shuffle(list2, rand); System.out.println("After shuffling: "+list2); System.out.println("array: "+Arrays.toString(ia)); }}

 

 

  

 

转载于:https://www.cnblogs.com/ITPower/p/8625627.html

你可能感兴趣的文章
P3932 浮游大陆的68号岛
查看>>
Ubuntu 10.10+安装Firefox 4.0正式版
查看>>
Using {{each}} in a template with an array of arrays
查看>>
第五百天 how can I 坚持
查看>>
集合-列表
查看>>
Adobe AIR对本地文件(XML文件)的操作
查看>>
adb 模拟器安装apk
查看>>
html5 图表相关
查看>>
咏南开发框架之自动升级
查看>>
简单MIS的构想
查看>>
简洁的ios小界面
查看>>
linux下mysql远程链接
查看>>
提取汉字拼音的首字母
查看>>
mysql快速入门
查看>>
JavaScript(五)语句
查看>>
jsvascript === 和==的区别
查看>>
SqlConnection中 Close()、Dispose()、Using()
查看>>
IMAC双系统WIN下截屏快捷键
查看>>
[译]Java 设计模式之适配器
查看>>
C# WinfForm 控件之dev报表 XtraReport(三) 动态数据绑定
查看>>