Java编程思想(第十一章持有对象)

Posted innndown

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java编程思想(第十一章持有对象)相关的知识,希望对你有一定的参考价值。

1. 第11章 持有对象

技术图片

java通过使用容器类来储存对象,与普通数组不同的是,普通数组的长度不可变。

1.1. 泛型与类型安全的容器

使用预定义的泛型,它指定了这个容器实例可以保存的类型,通过使用泛型,就可以在编译器防止将错误类型的对象放置到容器中。

public class gerbil {
    private int gerbilNumber;
    public gerbil(int gerbilNumber){
        this.gerbilNumber = gerbilNumber;
    }
    public void hop(){
        System.out.println(this.gerbilNumber);
        System.out.println("he is running");

    }
}


import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
    // write your code here
        List<gerbil> gerbils = new ArrayList<>();
        gerbils.add(new gerbil(2));
        gerbils.add(new gerbil(3));
        gerbils.add(new gerbil(4));
        gerbils.add(new gerbil(5));
        for (gerbil g:gerbils
             ) {
            g.hop();
        }
    }
}

1.2. 基本概念

java容器类库的用途是保存对象,将其划分为两个不同的接口:

  • Collection:一个独立元素的序列,这些元素都服从一条或多条规则,List必须按插入顺序保存元素,set不能有重复元素,Queue按照排队规则来确定对象产生的顺序。
  • Map:一组成对的键值对对象,允许你使用键值来查找值。

在进行容器创建时,可以创建接口的对象,可以方便于实现的修改,LinkList中具有List接口中没有实现的方法,TreeMap中也有Map中未实现的方法,在使用这些方法时,不可以向上转型:

List<gerbil> gerbils = new ArrayList<>();
List<gerbil> gerbils = new LinkedList<>();

1.3. 向容器添加元素和容器的打印

在java.utill包中的Arrays和Collections类中都有方法可以在Collenction中添加一组元素。

  • Arrays.asList()方法接受一个数组或是一个用逗号分隔的列表,转换为一个List对象

技术图片

  • Collections.addAll()方法接受一个Collection对象,以及一个数组或是一个用逗号分割的列表,将元素添加到Collection中,此方法效率高。

技术图片

  • Collection的构造方法也以接受另一个Collection对象,用来自身初始化。
  • Collection.addAll()成员方法只能接受另一个Collection对象作为参数,不能使用可变参数列表。
  • 也可直接使用Arrays.asList()方法的输出,将其当作List,但是得到的底层为数组长度不可变。
public class AddingGroup {
    public static void main(String[] args) {
        Collection<Integer> collection =
                new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
        Integer[] moreInts = { 6, 7, 8, 9, 10 };
        //int[] moreInts = { 6, 7, 8, 9, 10 };//进行自动装箱
        collection.addAll(Arrays.asList(moreInts));
        // Runs significantly faster, but you can't
        // construct a Collection this way:
        Collections.addAll(collection, 11, 12, 13, 14, 15);
        Collections.addAll(collection, moreInts);
        // Produces a list "backed by" an array:
        List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);//长度不可变
        list.set(1, 99); // OK -- modify an element
        list.add(21); // Runtime error because the
        // underlying array cannot be resized.
    }
}
public class AsListInference {
  public static void main(String[] args) {
    List<Snow> snow1 = Arrays.asList(
      new Crusty(), new Slush(), new Powder());

    // Won't compile:
    List<Snow> snow2 = Arrays.asList(
      new Light(), new Heavy());//jdk1.7/1.8支持

    // Collections.addAll() doesn't get confused:
    List<Snow> snow3 = new ArrayList<Snow>();
    Collections.addAll(snow3, new Light(), new Heavy());

    // Give a hint using an
    // explicit type argument specification:
    List<Snow> snow4 = Arrays.<Snow>asList(
       new Light(), new Heavy());
  }
} ///:~

对于基本数组的打印,可以使用Arrays.toString()方法

int[] a = {1,2,3};
System.out.println(Arrays.toString(a));
//Output:
[1, 2, 3]

对于容器的打印,可以使用容器内置的toString()方法

对于一个对象,在执行system.out.println()方法时,会自动调用toString方法,

技术图片

技术图片

技术图片

import java.util.*;
import static net.mindview.util.Print.*;

public class PrintingContainers {
  static Collection fill(Collection<String> collection) {
    collection.add("rat");
    collection.add("cat");
    collection.add("dog");
    collection.add("dog");
    return collection;
  }
  static Map fill(Map<String,String> map) {//方法的重载
    map.put("rat", "Fuzzy");
    map.put("cat", "Rags");
    map.put("dog", "Bosco");
    map.put("dog", "Spot");
    return map;
  } 
  public static void main(String[] args) {
    print(fill(new ArrayList<String>()));
    print(fill(new LinkedList<String>()));
    print(fill(new HashSet<String>()));
    print(fill(new TreeSet<String>()));
    print(fill(new LinkedHashSet<String>()));
    print(fill(new HashMap<String,String>()));
    print(fill(new TreeMap<String,String>()));
    print(fill(new LinkedHashMap<String,String>()));
  }
} /* Output:
[rat, cat, dog, dog]
[rat, cat, dog, dog]
[dog, cat, rat]
[cat, dog, rat]
[rat, cat, dog]
{dog=Spot, cat=Rags, rat=Fuzzy}
{cat=Rags, dog=Spot, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=Spot}
*///:~

1.4. List

list接口在collection接口的基础上添加了大量的方法,可以在List的中间插入和删除元素

  • ArrayList:方便于随机访问元素,如增与查,但是在List的中间插入和移动元素时较慢。
  • LinkedList:方便插入与删除,但在随机访问方面较慢,但是他的特性集较ArrayList更大。

    1.4.1. ArrayList

    技术图片

add(),contain(),remove(),get(),indexof(),remove(),sublist(),containall();removeall(),addall(),clear(),toarray()

//: holding/ListFeatures.java
import typeinfo.pets.*;
import java.util.*;
import static net.mindview.util.Print.*;

public class ListFeatures {
  public static void main(String[] args) {
    Random rand = new Random(47);
    List<Pet> pets = Pets.arrayList(7);//arraylist容器类
    print("1: " + pets);
    //1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug]
    Hamster h = new Hamster();
    pets.add(h); // Automatically resizes
    print("2: " + pets);
    //2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster]
    print("3: " + pets.contains(h));
    //3: true
    pets.remove(h); // Remove by object
    Pet p = pets.get(2);// get()得到下标值对应的值
    print("4: " +  p + " " + pets.indexOf(p));//返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。 
    //4: Cymric 2
    Pet cymric = new Cymric();
    print("5: " + pets.indexOf(cymric));
    //5: -1
    print("6: " + pets.remove(cymric));
    //6: false
    // Must be the exact object:
    print("7: " + pets.remove(p));
    //7: true
    print("8: " + pets);
    //8: [Rat, Manx, Mutt, Pug, Cymric, Pug]
    pets.add(3, new Mouse()); // Insert at an index
    print("9: " + pets);
    //9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug]


    List<Pet> sub = pets.subList(1, 4);//含低端点,不含高端点
    print("subList: " + sub);
    //subList: [Manx, Mutt, Mouse]
    print("10: " + pets.containsAll(sub));
    //10: true
    Collections.sort(sub); // In-place sort
    print("sorted subList: " + sub);
    //sorted subList: [Manx, Mouse, Mutt]
    // Order is not important in containsAll():
    print("11: " + pets.containsAll(sub));
    //11: true
    Collections.shuffle(sub, rand); // Mix it up使用默认的随机源随机排列指定的列表。
    print("shuffled subList: " + sub);
    //shuffled subList: [Mouse, Manx, Mutt]
    print("12: " + pets.containsAll(sub));
    //12: true


    print("9: " + pets);
    //9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug]
    List<Pet> copy = new ArrayList<Pet>(pets);
    sub = Arrays.asList(pets.get(1), pets.get(4));
    print("sub: " + sub);
    //sub: [Mouse, Pug]
    copy.retainAll(sub);
    print("13: " + copy);
    //13: [Mouse, Pug]


    copy = new ArrayList<Pet>(pets); // Get a fresh copy
    copy.remove(2); // Remove by index
    print("14: " + copy);
    //14: [Rat, Mouse, Mutt, Pug, Cymric, Pug]
    copy.removeAll(sub); // Only removes exact objects
    print("15: " + copy);
    //15: [Rat, Mutt, Cymric, Pug]
    copy.set(1, new Mouse()); // Replace an element
    print("16: " + copy);
    copy.addAll(2, sub); // Insert a list in the middle
    print("17: " + copy);
    print("18: " + pets.isEmpty());
    pets.clear(); // Remove all elements
    print("19: " + pets);
    print("20: " + pets.isEmpty());
    pets.addAll(Pets.arrayList(4));
    print("21: " + pets);
    Object[] o = pets.toArray();
    print("22: " + o[3]);
    Pet[] pa = pets.toArray(new Pet[0]);
    print("23: " + pa[3].id());
  }
} 
/*
16: [Rat, Mouse, Cymric, Pug]
17: [Rat, Mouse, Mouse, Pug, Cymric, Pug]
18: false
19: []
20: true
21: [Manx, Cymric, Rat, EgyptianMau]
22: EgyptianMau
23: 14
*///:~

remove()方法可以有移除标号和移除对象,移除对象时重写equals方法,重写hashcode方法。

在使用下标迭代删除对象时应该注意倒序删除

//倒序删除元素
for(int i=list.size()-1;i>=0;i--){
    if(list.get(i)==3){
        list.remove(i);
    }
}
System.out.println(list);
//迭代器删除元素
Iterator<Integer> it=list.iterator();
    while(it.hasNext()){
        if(it.next()==3){
            it.remove();
        }
        }
System.out.println(list);

remove()方法源码:

    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

list遍历方法

//**********三种遍历方式*************
        for(int i = 0;i<list1.size();i++) {
            System.out.println(list1.get(i));
        }//
        
        for(String s:list1) {
            System.out.println(s);
        }
        
        Iterator it = list1.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
        
    }

Integer的equal()实现源码

技术图片

1.4.2. LinkedList

技术图片

LinkedList也和ArrayList一样也实现了基本的list接口,在插入和删除方面比较高效,随机访问方面不如ArrayList。
以下是特有的方法。

//: holding/LinkedListFeatures.java
import typeinfo.pets.*;
import java.util.*;
import static net.mindview.util.Print.*;

public class LinkedListFeatures {
  public static void main(String[] args) {
    LinkedList<Pet> pets =
      new LinkedList<Pet>(Pets.arrayList(5));
    print(pets);
    // Identical:
    print("pets.getFirst(): " + pets.getFirst());//返回此列表中的第一个元素。
    print("pets.element(): " + pets.element());//检索但不删除此列表的头(第一个元素)。 
    // Only differs in empty-list behavior:
    print("pets.peek(): " + pets.peek());
    //检索但不删除此列表的头(第一个元素),上面两个方法在List=null时抛出NoSuchElement异常,这个方法会返回null
    // Identical; remove and return the first element:
    print("pets.remove(): " + pets.remove());//在不带参数时,表示删除列表的头第一个元素
    print("pets.removeFirst(): " + pets.removeFirst());//删除列表的头第一个元素
    // Only differs in empty-list behavior:
    print("pets.poll(): " + pets.poll());
    //弹出堆栈中的第一个元素,上面两个方法在List=null时抛出NoSuchElement异常,这个方法会返回null
    print(pets);
    pets.addFirst(new Rat());//将指定的元素追加到此列表的头。
    print("After addFirst(): " + pets);//开头插入指定的元素。
    pets.offer(Pets.randomPet());//将指定的元素添加为此列表的尾部(最后一个元素)。 
    print("After offer(): " + pets);
    pets.add(Pets.randomPet());//将指定的元素追加到此列表的末尾。
    print("After add(): " + pets);
    pets.addLast(new Hamster());//将指定的元素追加到此列表的末尾。
    print("After addLast(): " + pets);
    print("pets.removeLast(): " + pets.removeLast());//删除列表的最后一个元素
  }
} /* Output:
[Rat, Manx, Cymric, Mutt, Pug]
pets.getFirst(): Rat
pets.element(): Rat
pets.peek(): Rat
pets.remove(): Rat
pets.removeFirst(): Manx
pets.poll(): Cymric
[Mutt, Pug]
After addFirst(): [Rat, Mutt, Pug]
After offer(): [Rat, Mutt, Pug, Cymric]
After add(): [Rat, Mutt, Pug, Cymric, Pug]
After addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster]
pets.removeLast(): Hamster
*///:~

1.5. Stack(栈)

:是一种“后进先出的容器”,即最后一个压入栈中的元素,总是第一个出来。

  • LinkedList具有可以实现栈的所有功能的方法,也可以用LinkList创建一个Stack类。
  • 也可以使用java.util包中的stack类。
import java.util.LinkedList;
 
public class Stack<T> {
    private LinkedList<T> storage=new LinkedList<T>();
    public void push(T t){
        storage.addFirst(t);在该列表开头插入指定的元素。
    }//向栈中添加元素
    public T peek(){
        return storage.getFirst();//返回此列表中的第一个元素。
    }//查看栈顶元素
    public T pop(){
        return storage.removeFirst();//从此列表中删除并返回第一个元素。
    }//移除栈顶元素
    public boolean isEmpty(){
        return storage.isEmpty();
    }//判断栈是否为空
    public String toString(){
        return storage.toString();
    }
}

两种栈的比较

//: holding/StackCollision.java
import net.mindview.util.*;

public class StackCollision {
  public static void main(String[] args) {

    
    net.mindview.util.Stack<String> stack =
      new net.mindview.util.Stack<String>();
    for(String s : "My dog has fleas".split(" "))
      stack.push(s);
    while(!stack.empty())
      System.out.print(stack.pop() + " ");
    System.out.println();

    
    java.util.Stack<String> stack2 =
      new java.util.Stack<String>();
    for(String s : "My dog has fleas".split(" "))
      stack2.push(s);
    while(!stack2.empty())
      System.out.print(stack2.pop() + " ");
  }
} /* Output:
fleas has dog My
fleas has dog My
*///:~

1.6. Set

Set不保存重复元素,通过equals(),hashcode()方法判断两个元素是否相同。

HashSet使用了HASH散列算法,TreeSet使用了红黑树,LinkedHashSet也使用了散列表,

//HashSet示例,hash输出为无序的:
//: holding/SetOfInteger.java
import java.util.*;

public class SetOfInteger {
  public static void main(String[] args) {
    Random rand = new Random(47);
    Set<Integer> intset = new HashSet<Integer>();
    for(int i = 0; i < 10000; i++)
      intset.add(rand.nextInt(30));
    System.out.println(intset);
  }
} /* Output:
[15, 8, 23, 16, 7, 22, 9, 21, 6, 1, 29, 14, 24, 4, 19, 26, 11, 18, 3, 12, 27, 17, 2, 13, 28, 20, 25, 10, 5, 0]
*///:~
//TreeSet示例,treeset为有序的:
//: holding/SortedSetOfInteger.java
import java.util.*;

public class SortedSetOfInteger {
  public static void main(String[] args) {
    Random rand = new Random(47);
    SortedSet<Integer> intset = new TreeSet<Integer>();
    for(int i = 0; i < 10000; i++)
      intset.add(rand.nextInt(30));
    System.out.println(intset);
  }
} /* Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
*///:~

Set常用操作之一就是使用contains用来测试归属性

public class hashset {
    private int name;
    private int age;
    public int hashCode() {
        
        return Objects.hash(name,age);
        
    }
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<String>();
        set.size();
        set.clear();
        set.contains("aaa");
        set.remove("aas");
        set.add("122");
        set.add("月月");
        set.add("122");//String类重写了equal()方法
        set.add("月月");//
        
        //System.out.println(null==null);
        //********************遍历**********************
        
        for(String s:set) {
            System.out.println(s);
        }
        Iterator it = set.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

1.7. Map

对于HashMap而言,key是唯一的,不可以重复的。所以,以相同的key 把不同的value插入到 Map中会导致旧元素被覆盖,只留下最后插入的元素。

//: holding/Statistics.java
// Simple demonstration of HashMap.
import java.util.*;

public class Statistics {
  public static void main(String[] args) {
    Random rand = new Random(47);
    Map<Integer,Integer> m =new HashMap<Integer,Integer>();
    for(int i = 0; i < 100; i++) {
      // Produce a number between 0 and 20:
      int r = rand.nextInt(20);
      Integer freq = m.get(r);
      m.put(r, freq == null ? 1 : freq + 1);
    }
    System.out.println(m.get(1));//根据key查找value
    System.out.println(m.containsKey(1));//判断是否包含这个key
    System.out.println(m.containsValue(5));//判断是否有这个value值
    System.out.println(m);
  }
} /* Output:
6
true
true
{0=4, 1=6, 2=9, 3=3, 4=6, 5=3, 6=5, 7=4, 8=7, 9=6, 10=5, 11=3, 12=3, 13=5, 14=6, 15=4, 16=5, 17=5, 18=8, 19=3}
*///:~

Map与list和其他的Collection一样,可以很容易的扩展到多维,可以将容器组合起来形成强大的数据结构,例如可以生成一个人有多个宠物的数据结构,如Map<Person,List>:

//: holding/MapOfList.java
package holding;
import typeinfo.pets.*;
import java.util.*;
import static net.mindview.util.Print.*;

public class MapOfList {
  public static Map<Person, List<? extends Pet>>
    petPeople = new HashMap<Person, List<? extends Pet>>();
  static {
    petPeople.put(new Person("Dawn"),
      Arrays.asList(new Cymric("Molly"),new Mutt("Spot")));

    petPeople.put(new Person("Kate"),
      Arrays.asList(new Cat("Shackleton"),
        new Cat("Elsie May"), new Dog("Margrett")));

    petPeople.put(new Person("Marilyn"),
      Arrays.asList(
       new Pug("Louie aka Louis Snorkelstein Dupree"),
       new Cat("Stanford aka Stinky el Negro"),
       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("Freckly")));
  }
  public static void main(String[] args) {
    print("People: " + petPeople.keySet());
    //People: [Person Luke, Person Marilyn, Person Isaac, Person Dawn, Person Kate]
    print("Pets: " + petPeople.values());
    //Pets: [[Rat Fuzzy, Rat Fizzy], [Pug Louie aka Louis Snorkelstein Dupree, Cat Stanford aka Stinky el Negro, Cat Pinkola], [Rat Freckly], [Cymric Molly, Mutt Spot], [Cat Shackleton, Cat Elsie May, Dog Margrett]]
    for(Person person : petPeople.keySet()) {
      print(person + " has:");
      for(Pet pet : petPeople.get(person))
        print("    " + pet);
    /*
    Person Luke has:
    Rat Fuzzy
    Rat Fizzy
Person Marilyn has:
    Pug Louie aka Louis Snorkelstein Dupree
    Cat Stanford aka Stinky el Negro
    Cat Pinkola
Person Isaac has:
    Rat Freckly
Person Dawn has:
    Cymric Molly
    Mutt Spot
Person Kate has:
    Cat Shackleton
    Cat Elsie May
    Dog Margrett
    */
    }
  }
} 

map可以通过KeySet()方法来返回Key的Set集合,

技术图片

也可以通过value()方法返回其value的Collection视图,可用在for-each中遍历

技术图片

1.8. Queue(队列)

技术图片

队列是一个先进先出的容器,LinkedList提供方式支持队列的行为实现了Queue的接口:

它在LinkedList的基础上添加了element(),offer(),peek(),poll(),和remove()方法,可以使其成为一个Queue的实现。

//: holding/QueueDemo.java
// Upcasting to a Queue from a LinkedList.
import java.util.*;

public class QueueDemo {
  public static void printQ(Queue queue) {
    while(queue.peek() != null)
      System.out.print(queue.remove() + " ");//移除并返回队列头
      System.out.print(queue.poll() + " ");//移除并返回队列头
      System.out.print(queue.element() + " ");//  不移除并返回队列头
      System.out.print(queue.peek() + " ");//  不移除并返回队列头

    System.out.println();
  }
  public static void main(String[] args) {
    Queue<Integer> queue = new LinkedList<Integer>();
    Random rand = new Random(47);
    for(int i = 0; i < 10; i++)
      queue.offer(rand.nextInt(i + 10));
    printQ(queue);
    Queue<Character> qc = new LinkedList<Character>();
    for(char c : "Brontosaurus".toCharArray())
      qc.offer(c);//将指定的元素添加为此列表的尾部(最后一个元素)。
    printQ(qc);
  }
} /* Output:
8 1 1 1 5 14 3 1 0 1
B r o n t o s a u r u s
*///:~

1.8.1. priorityQueue队列

先进先出队列是最基本的队列规则,即下一个元素应该是等待时间最长的元素。

优先级队列的下一个弹出对象是最需要的元素(具有最高的优先级),所以在调用PriorityQueue中的offer()方法时,这个对象会在队列中被排序,默认的排序为自然排序,但可以通过Comparator比较器来修改顺序。

1.9. 迭代器

Iterator是一种设计模式,java的Iterator只能单向移动,这个Iterator只能用来:

  • 使用方法Iterater()返回一个Iterator对象,Iterator准备返回序列的第一个元素。
  • 使用next()获取序列中的下一个元素。
  • 使用hasNext()判断序列中是否有下一个元素。
  • 使用remove()将迭代器返回的元素删除
//: holding/SimpleIteration.java
import typeinfo.pets.*;
import java.util.*;

public class SimpleIteration {
  public static void main(String[] args) {
    List<Pet> pets = Pets.arrayList(12);
    Iterator<Pet> it = pets.iterator();
    while(it.hasNext()) {//判断是否存在下一个元素
      Pet p = it.next();//获取返回的元素
      System.out.print(p.id() + ":" + p + " ");
    }
    System.out.println();
    // A simpler approach, when possible:
    for(Pet p : pets)
      System.out.print(p.id() + ":" + p + " ");
    System.out.println();   
    // An Iterator can also remove elements:
    it = pets.iterator();
    for(int i = 0; i < 6; i++) {
      it.next();//获取返回的元素
      it.remove();//将返回的元素删除
    }
    System.out.println(pets);
  }
} /* Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster
[Pug, Manx, Cymric, Rat, EgyptianMau, Hamster]
*///:~

set和list都可以使用这种方法进行遍历,map要复杂一点

//: holding/CrossContainerIteration.java
import typeinfo.pets.*;
import java.util.*;

public class CrossContainerIteration {
  public static void display(Iterator<Pet> it) {
    while(it.hasNext()) {
      Pet p = it.next();
      System.out.print(p.id() + ":" + p + " ");
    }
    System.out.println();
  } 
  public static void main(String[] args) {
    ArrayList<Pet> pets = Pets.arrayList(8);
    LinkedList<Pet> petsLL = new LinkedList<Pet>(pets);
    HashSet<Pet> petsHS = new HashSet<Pet>(pets);
    TreeSet<Pet> petsTS = new TreeSet<Pet>(pets);
    display(pets.iterator());
    display(petsLL.iterator());
    display(petsHS.iterator());
    display(petsTS.iterator());
  }
} /* Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
4:Pug 6:Pug 3:Mutt 1:Manx 5:Cymric 7:Manx 2:Cymric 0:Rat
5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug 0:Rat
*///:~

ListIterator

ListIterator是一个更强大的子类型提供了双向访问的功能,Iterator只能向前移动,但是ListIterator可以双向移动,还可以产生迭代子的前一个位置或者后一个位置的索引,

还可以像remove()方法一样,使用set()方法来对该元素进行替换,

并且可以使用listiterator(n)方法让迭代子从下标为n开始迭代。

//: holding/ListIteration.java
import typeinfo.pets.*;
import java.util.*;

public class ListIteration {
  public static void main(String[] args) {
    List<Pet> pets = Pets.arrayList(8);
    ListIterator<Pet> it = pets.listIterator();
    while(it.hasNext())
      System.out.print(it.next() + ", " + it.nextIndex() +
        ", " + it.previousIndex() + "; ");
    System.out.println();
    // Backwards:
    while(it.hasPrevious())
      System.out.print(it.previous().id() + " ");
    System.out.println();
    System.out.println(pets);   
    it = pets.listIterator(3);
    while(it.hasNext()) {
      it.next();
      it.set(Pets.randomPet());
    }
    System.out.println(pets);
  }
} /* Output:
Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, 5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7;
7 6 5 4 3 2 1 0
[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx]
[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, EgyptianMau]
*///:~

以上是关于Java编程思想(第十一章持有对象)的主要内容,如果未能解决你的问题,请参考以下文章

《Java编程思想》笔记 第十一章 持有对象

《JAVA编程思想》学习笔记——第十一章 持有对象

“持有对象”小记

第十一章 持有对象

第十一章:持有对象

java持有对象容器类及ArrayList