读书笔记 Thinking In Java第11章“持有对象”

*C出身,机缘巧合下进入Java的世界快一年了,上个星期决定经营自己的博客。舍弃了自己之前用的账号,重新申请了一个,寓意一个新的开端。第一篇,总结一下java编程思想第11章,请大家指教。*

“如果一个程序只包含固定数量的且其生命周期已知的对象,那么这是一个非常简单的程序”

11.1 泛型和类型安全的容器

//不使用泛型:(简单易懂,只展示主要代码)
ArrayList apples=new ArrayList();
apples.add(new Apple());
apples.add(new Orange());
for(int i=0;i<apples.size();i++){
   ((Apple)Apples.get(i)).id();
}
/*
* 为什么能把Orange对象放进容器呢?因为它
* 自动继承了Object,ArrayList保存      
* 的是Object。当你在使用ArrayList的
*get()方法来取出你认为是Apple的对象时,
* 你得到的只是object引用,必须将其转型
* 为Apple,否则就会得到语法错误 。
*/
//使用泛型
ArrayList<Apple> apples=new ArrayList<Apple>();
apples.add(new Apple());
//apples.add(new Orange());不注释掉会产生编译期错误
for(int i=0;i<apples.size();i++){
   Apples.get(i).id();
}
//向上转型也可以作用于泛型
class Gala extends Apple{};
class Fuji extends Apple{};
ArrayList<Apple> apples=new ArrayList<Apple>();
apples.add(new Apple());
apples.add(new Gala());
apples.add(new Fuji());
for(Apple a : apples){
  System.out.println(c);
}
/*程序将会输出Object默认的toString()方法产生的类名和hashCode()方法生成的散列码,第17章介绍散列码。
*/

11.3添加一组元素
Arrays.asList()方法接受一个数组或者是一个用逗号分割的元素列表,并将其转换为一个List对象。
Collections.addAll()方法接受一个Collection对象,以及一个数组或者一个用逗号分割的列表,将元素添加到Collection。
11.4 容器的打印
我们已经知道基本的知识:Set不能有重复元素,List必须按照插入的顺序保存元素,Queue一端插入一端移除对象,Map的对象是一组成对的键值对,允许你使用键来查找值。容器的打印遵循基本规则:
LinkedHashSet 原序打印
TreeSet 升序
HashSet 速度最快,无序
LinkedHashMap 原序
TreeMap 升序
HashMap 最快,无序
这里有一个面试官大概率会问的问题:有没有有顺序的map实现类?有哪几个?是如何保证它的顺序的?HashMap是无序的,它的随机存取和快速查找是如何实现的?关于这几个问题,在另一篇里专门讲解
11.6迭代器(可以理解为一个通用容器,有其自己特殊的方法)
Java的Iterator只能单向移动,
1) 使用方法iterator()要求容器返回一个Iterator。
2)使用 next()方法获得序列中的下一个元素。
3)使用hasNext()检查序列中是否还有元素。
4)使用remove()将迭代器新近返回的元素删除。

List<Pet> pets=Pets.arrayList(23);
Iterator<Pet> it=pets.iterator();
while(it.hasNext()){
    Pet p=it.next();
    sysout;
}

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

import java.util.List;
import java.util.ListIterator;
import typeinfo.pets.*;
public class ThinkingInJava {
   public static void main(String[] args){
       List<Pet> pets=Pets.arrayList(5);
     //调用listIterator()方法产生指向List的迭代器
     ListIterator<Pet> lit =pets.listIterator();
     while(lit.hasNext())
     {
         System.out.print (lit.next()+","+lit.nextIndex()+","+lit.previousIndex()+";");;
     }
     System.out.println();
     while(lit.hasPrevious())
     {
         System.out.print (lit.previous().id()+" ");
     }
     System.out.println();
     //一开始就指向列表索引为2的迭代器
     lit=pets.listIterator(2);
     while(lit.hasNext()){
         lit.next();
         //用set()方法替换
         lit.set(Pets.randomPet());
     }
     System.out.println(pets);
   }
}
/*输出结果:
 * Rat,1,0;Manx,2,1;Cymric,3,2;Mutt,4,3;Pug,5,4;
   4 3 2 1 0 
   [Rat, Manx, Cymric, Pug, Manx]
 */

LinkedList、Stack、Set比较简单,不再深究。
11.10 Map

“将对象映射到其他对象的能力是一种解决编程问题的杀手锏。”

有这样一个需求,检查Java的Random的随机性,使用Map很好解决。

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThinkingInJava {
   public static void main(String[] args){
       Random rand=new Random(23);
       Map<Integer,Integer> map=new HashMap<Integer,Integer>();
           int r=rand.nextInt(20);
           Integer freq=map.get(r);
           map.put(r,freq==null?1:freq+1);
       }
       System.out.println(map);
   }
}
/*输出结果
 *{0=40, 1=54, 2=47, 3=59, 4=50, 5=35, 6=41, 7=63,
 * 8=47, 9=43, 10=47, 11=59, 
 *12=63, 13=46, 14=41, 15=52,
 * 16=56, 17=55, 18=50, 19=52}
 */

Map与数组和其他的Collection一样,可以很容易的拓展到多维。假设你要跟踪一个拥有很多宠物的人,你所需的只是一个Map < Person,List < Pet >>

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import typeinfo.pets.*;

public class ThinkingInJava {
    public static Map<Person, List<?extends Pet>>
    petPeople=new HashMap<Person,List<?extends Pet>>();
    static{
        petPeople.put(new Person("Lebron"),Arrays.asList(new Cymric("Cymric"),new Mutt("Mutt")));
        petPeople.put(new Person("James"),Arrays.asList(new Cat("Cat"),new Dog("Dog")));
        petPeople.put(new Person("Zheng"),Arrays.asList(
                new Pug("Pug"),
                new Cat("Aka"),
                new Cat("Pinkola"))
                );
        petPeople.put(new Person("Luke"),
                Arrays.asList(new Rat("Fuzzy"),new Rat("Fizzy")));
        petPeople.put(new Person("Isaac"),
                Arrays.asList(new Rat("Rreckly")));
    }
   public static void main(String[] args){
       //keySet()方法产生了所有键组成的Set
       System.out.println("People: "+petPeople.keySet());
       System.out.println("Pets: "+petPeople.values());
       for(Person person : petPeople.keySet()){
           System.out.println(person + " has:");
           for(Pet pet :petPeople.get(person)){
               System.out.println(" "+pet);
           }
       }

   }
}
/*输出结果
 *People: [Person Lebron, Person Isaac, Person Luke, Person Zheng, Person James]
Pets: [[Cymric Cymric, Mutt Mutt], [Rat Rreckly], [Rat Fuzzy, Rat Fizzy], [Pug Pug, Cat Aka, Cat Pinkola], [Cat Cat, Dog Dog]]
Person Lebron has:
 Cymric Cymric
 Mutt Mutt
Person Isaac has:
 Rat Rreckly
Person Luke has:
 Rat Fuzzy
 Rat Fizzy
Person Zheng has:
 Pug Pug
 Cat Aka
 Cat Pinkola
Person James has:
 Cat Cat
 Dog Dog
 */

11.11 Queue
队列是一个典型的先入先出(FIFO)的容器,在并发编程中非常重要,它们可以安全的将一个对象从一个任务传输到另一个任务。
LinkedList提供了方法以支持队列的行为,并且实现了Queue接口,因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue。看代码:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class QueueDemo{
    public static void printQ(Queue queue){
        //peek()返回队头,队列为空返回null
        while(queue.peek()!=null){
            //remove()移除并返回对头,队列为空抛出异常
            System.out.print(queue.remove()+" ");
        }
        System.out.println();
    }

   public static void main(String[] args){
      Queue<Integer> queue=new LinkedList<Integer>();
      Random random=new Random(47);
      for(int i=0;i<10;i++){
          //offer()在允许的情况下将一个元素插入到队尾,或者返回false
          queue.offer(random.nextInt(i+10));
      }
      printQ(queue);
      Queue<Character> qCharacters=new LinkedList<Character>();
      for(char c : "Brontosaurus".toCharArray()){
          qCharacters.offer(c);
      }
      printQ(qCharacters);
   }
}
/*输出结果
8 1 1 1 5 14 3 1 0 1 
B r o n t o s a u r u s 
 */

优先级队列声明下一个弹出元素是最重要的元素。例如,在飞机场,快要起飞的乘客可以在办理登机手续时排到队头。为了提供这种行为的一种自动实现,PriorityQueue添加到JAVA SE5中。
当你在PriorityQueue上调用offer()方法来插入一个对象时,这个对象会在队列中被排序,默认的排序是自然增序,但是你可以通过提供自己的Comparator来修改这个顺序。看代码:

import QueueDemo.QueueDemo;
import java.util.*;

public class ThinkingInJava {

   public static void main(String[] args){
     PriorityQueue<Integer> priorityQueue=new PriorityQueue<Integer>();
     Random random=new Random(45);
     for(int i=0;i<10;i++){
         priorityQueue.offer(random.nextInt(i+10));
     }
     QueueDemo.printQ(priorityQueue);
     List<Integer> integers=Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25);
     priorityQueue=new PriorityQueue<Integer>(integers);
     QueueDemo.printQ(priorityQueue);
     priorityQueue=new PriorityQueue<Integer>(
             integers.size(),Collections.reverseOrder());
     priorityQueue.addAll(integers);
     QueueDemo.printQ(priorityQueue);

     String fact="The King is still the King!";
     List<String> strings=Arrays.asList(fact.split(""));
     PriorityQueue<String> stringPQ=new PriorityQueue<String>(strings);
     QueueDemo.printQ(stringPQ);
     //??第一个参数有啥用,我随便输入个非零整数结果不变怎么回事?
     stringPQ=new PriorityQueue<String>(
             strings.size(),Collections.reverseOrder());
     stringPQ.addAll(strings);
     QueueDemo.printQ(stringPQ);

     Set<Character> charSet=new HashSet<Character>();
     for(char c : fact.toCharArray()){
         charSet.add(c);
     }
     PriorityQueue<Character> characterPQ=new PriorityQueue<Character>(charSet);
     QueueDemo.printQ(characterPQ);
   }
}
/*输出结果
0 3 5 6 8 9 11 12 12 16 
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 
The King is still the King!
          ! K K T e e g g h h i i i i l l n n s s t t 
t t s s n n l l i i i i h h g g e e T K K !           
  ! K T e g h i l n s t 
 */

简单的容器分类
简单的容器分类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值