- 11.1 泛型和类型安全容器
- 11.2 基本概念
- 11.3 添加一组元素
- 11.4 容器的打印
- 11.5 List
- 11.6 迭代器
- 11.7 LinkedList
- 11.8 Stack
- 11.9 Set
- 11.10 Map
- 11.11 Queue
- 11.12 Collection 和 Iteration
- 11.13 Foreach与迭代器
- 11.14 总结
- 数组:保存一组对象最有效方式,如保存一组基本类型数据。缺点:尺寸固定限制
- 容器:集合类 是容器的子集。自动调整尺寸。17章深入讲解。
11.1 泛型和类型安全容器
没有使用泛型,ArrayList保存Object对象,
保存不同对象类型后,在运行时转型会异常错误。
package chapter11holding;
import java.util.ArrayList;
class Apple{
private static long counter;
private final long id = counter++;
public long id(){return id;}
}
class Orange{
}
public class ApplesAndOrangesWithoutGenerics {
public static void main(String[] args) {
ArrayList apples = new ArrayList();
for(int i = 0; i < 3; i++)
apples.add(new Apple());
apples.add(new Orange()); // 没有阻止 加入Orange
for (int i = 0; i < apples.size();i ++)
((Apple)apples.get(i)).id(); //只有在运行时候才检测出
}
}
使用预定义的泛型 ArrayList
使用泛型,编译器会检查放入容器的对象类型,使用容器对象时,可以使用清晰的语法。
package chapter11holding;
import java.util.ArrayList;
public class ApplesAndOrangesWithGenerics {
public static void main(String[] args) {
ArrayList<Apple> apples = new ArrayList<Apple>();
for (int i = 0; i < 3; i++)
apples.add(new Apple());
//apples.add(new Orange()); //编译期报错
for (int i = 0; i < apples.size(); i++)
System.out.println(apples.get(i).id());// 取出不需要 类型转换
for (Apple a : apples) //foreach语法
System.out.println(a.id());
}
}
泛型 向上转型
package chapter11holding;
import java.util.ArrayList;
class GrannySimith extends Apple {
}
class Gala extends Apple { }
class Fuji extends Apple { }
class Braeburn extends Apple { }
public class GenericsAndUpcasting {
public static void main(String[] args) {
ArrayList<Apple> apples = new ArrayList<Apple>();
apples.add(new GrannySimith());
apples.add(new Gala());
apples.add(new Fuji());
apples.add(new Braeburn());
for (Apple apple : apples) // 向上转型
System.out.println(apple);
}
}
/*
chapter11holding.GrannySimith@266474c2 //类名+对象+散列码17章
chapter11holding.Gala@6f94fa3e
chapter11holding.Fuji@5e481248
chapter11holding.Braeburn@66d3c617
*/
作业1
package chapter11holding.e1;
import java.util.ArrayList;
class Gerbil { // 沙鼠
private final int gerbilNumber;
public Gerbil(int gerbilNumber){
this.gerbilNumber = gerbilNumber;
}
public String toString(){
return "Gerbil" + gerbilNumber;
}
void hop() {
System.out.println(this + " hop()");
}
}
public class E1 {
public static void main(String[] args) {
ArrayList<Gerbil> gerbils = new ArrayList<Gerbil>();
for (int i = 0; i < 3; i++)
gerbils.add(new Gerbil(i));
for (int i = 0; i< 3; i++)
gerbils.get(i).hop();
for (Gerbil gerbil : gerbils) {
gerbil.hop();
}
}
}
/*
Gerbil0 hop()
Gerbil1 hop()
Gerbil2 hop()
Gerbil0 hop()
Gerbil1 hop()
Gerbil2 hop()
*/
11.2 基本概念
容器分为两类:
- Collection 序列
- list 接口
- ArrayList 插入顺序保存元素 查询快,增删改慢
- LinkedList 插入顺序保存元素 查询慢,增删改快
- Set 接口:不能重复
- HashSet 以相当复杂的方式来存储元素,这种技术是最快的获取元素的方式
- TreeSet:按照结果的升序保存元素
- 可以自行执行排序方式。默认是按照字典顺序排序。如果想按照字母顺序排序,可以向TreeSet构造器中传入String。CASE_INSENTIVE_ORDER.
- LinkedHashSet:按照添加顺序保存元素
- Queue接口
- list 接口
- Map 键值对
- HashMap:已相当复杂的方式来存储元素(散列函数),这种技术是最快的获取元素的方式
- TreeMap:按照比较结果的升序保存,元素存储在红黑树数据结构。
- LinkedHashMap:按照添加顺序保存元素。同时还保留了HashMap的查询速度。
定义集合时,使用向上转型,是好习惯。
Collection
唯一缺点,额外方法点调用,需要使用ArrayList来定义
package chapter11holding;
import java.util.ArrayList;
import java.util.Collection;
public class SimpleCollection {
public static void main(String[] args) {
Collection<Integer> c = new ArrayList<Integer>();
for (int i = 0;i < 10; i++ )
c.add(i);
for (Integer integer:c)
System.out.println(integer);
}
}
作业2
package chapter11holding.e2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class SimpleCollection {
public static void main(String[] args) {
Collection<Integer> c = new HashSet<>();
for (int i = 10;i > 0; i-- )
c.add(i); // autoboxing 自动装箱
for (Integer integer:c)
System.out.println(integer);
}
}
/* 通常 Set 不按插入顺序保存元素
1
2
3
4
5
6
7
8
9
10
*/
作业3
package chapter11holding.e3;
//
import java.util.ArrayList;
interface Selector { // 迭代器模式
boolean end();
Object current();
void next();
}
public class Sequence {
private ArrayList<Object> items;
public void add(Object x) {
items.add(x);
}
private class SequenceSelector implements Selector {
private int i = 0;
@Override
public boolean end() {
return i == items.size();
}
@Override
public Object current() {
return items.get(i);
}
@Override
public void next() {
if (i < items.size()) i++;
}
}
public Selector selector() {
return new SequenceSelector();
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
for (int i = 0; i < 5; i++)
sequence.add(Integer.toString(i));
Selector selector = sequence.selector();
while (!selector.end()) {
System.out.println(selector.current() + " ");
selector.next();
}
}
}
11.3 添加一组元素
package chapter11holding;
import java.util.*;
public class AddingGroups {
public static void main(String[] args) {
//Arrays.asList() 接受一个数组或是用逗号分隔的元素列表,也可以用可变参数,然后将其转为一个List对象。
//Collection的构造器可以接受另一个Collection,可以使用Arrays.asList()方法作为构造器输入,但是只能接收Collection,所以不太灵活,
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
Integer[] moreInts = {6, 7, 8, 9, 10};
collection.addAll(Arrays.asList(moreInts));
//一般我们可以采用将Arrays.asList()作为参数,然后在调用collection.addAll()方法。
//Collections.addAll()方法接受一个Collection对象,以及一个数组或是一个用逗号分隔的列表,并将元素添加到Collection中。
Collections.addAll(collection, 11, 12, 13, 14, 15);
Collections.addAll(collection, moreInts);
// 底层是数组,不能调整大小,如果要使用listadd()或者list.delete()方法就会出现异常。
List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
list.set(1, 99);
//Arrays.asList()会返回一个ArrayList,但是要特别注意,这个ArrayList是Arrays类的静态内部类,并不是java.util.ArrayList类。
// java.util.Arrays.ArrayList类实现了set(),get(),contains()方法,
// 但是并没有实现增加元素的方法(事实上是可以调用add方法,但是没有具体实现,仅仅抛出UnsupportedOperationException异常),
// 因此它的大小也是固定不变的。
list.add(21); // public void add(int index, E element) {throw new UnsupportedOperationException();}
}
}
11.4 容器的打印
Java容器类库中的两种主要类型,它们的区别在于容器中每个"槽"保存的元素个数
Clollection容器只能在保存一个元素,此类容器包括:
List,它以特定顺序保存一组元素
Set对于每个值都只保存一个对象,不能有重复元素
Queue 只允许在容器的一"端"插入对象,并从另一端移除对象(很像数据结构的队列)
Map在每个槽内保存了两个对象,即键和与之想关联的值
Map允许你将某些对象与其他一些对象关联起来的关联数组,
- 数组的打印:Arrays.toString(数组名)
- 容器:直接打印容器名
package chapter11holding;
import java.util.*;
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) {
System.out.println(fill(new ArrayList<String>()));
System.out.println(fill(new LinkedList<String>()));
System.out.println(fill(new HashSet<String>()));
System.out.println(fill(new TreeSet<String>()));
System.out.println(fill(new LinkedHashSet<String>()));
System.out.println(fill(new HashMap<String,String>()));//HashMap提供了最快的速度
System.out.println(fill(new TreeMap<String,String>()));//TreeMap按比较的结果升序保存键
System.out.println(fill(new LinkedHashMap<String,String>()));//LinkedhashMap按插入顺序保存键,并保留了HashMap的速度
}
}
作业4
package chapter11holding.e4;
import net.mindview.util.Generator;
import java.util.*;
class NameGenerator implements Generator<String> {
String[] characters = {"Snow White", "Star Wars", "Sleepy"};
int next;
@Override
public String next() {
String r = characters[next];
next = (next + 1) % characters.length; //循环获取
return r;
}
}
public class MovieNameGenerator {
private static final NameGenerator mng = new NameGenerator();
static String[] fill(String[] array) {
for (int i = 0; i < array.length; i++)
array[i] = mng.next();
return array;
}
static Collection<String> fill(Collection<String> collection) {
for (int i = 0; i < 5; i++) {
collection.add(mng.next());
}
return collection;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(fill(new String[5])));
System.out.println(fill(new ArrayList<String>()));
System.out.println(fill(new LinkedList<String>()));
System.out.println(fill(new HashSet<String>()));
System.out.println(fill(new LinkedHashSet<String>()));
System.out.println(fill(new TreeSet<String>()));
}
}
11.5 List
list承诺可以将元素维护在特定的序列中,List接口在Collection的基础上添加了大量的方法,使得可以在List的中间插入和移动元素
有两种List
基本的ArrayList,它长于随机访问元素,但时在List的中间插入和移除元素较慢
LinkedList,它通过代价较低的在List中间进行的插入和删除操作,提供了优化的顺序访问.LinkedList在随机访问方面相对较慢,但它的特性较ArrayList更大
package chapter11holding;
import typeinfo.pets.*;
import java.util.*;
public class ListFeatures {
public static void main(String[] args) {
Random rand = new Random(47);
List<Pet> pets = Pets.arrayList(7);
System.out.println("1: " + pets);
Hamster h = new Hamster();
pets.add(h); //自动调整size
System.out.println("2: " + pets);
System.out.println("3: " + pets.contains(h));
pets.remove(h);
Pet p = pets.get(2);
System.out.println("4: " + p + " " + pets.indexOf(p));
Pet cymric = new Cymric();
System.out.println("5: " + pets.indexOf(cymric));
System.out.println("6: " + pets.remove(cymric));
System.out.println("7: " + pets.remove(p));
System.out.println("8: " + pets);
pets.add(3, new Mouse());
System.out.println("9: " + pets);
List<Pet> sub = pets.subList(1, 4);
System.out.println("sublist: " + sub);
System.out.println("10: " + pets.containsAll(sub));
Collections.sort(sub);//In-place sort
System.out.println("sorted sublist: " + sub);
System.out.println("11: " + pets.containsAll(sub));// containsAll 与顺序无关
Collections.shuffle(sub, rand);
System.out.println("12: " + pets.containsAll(sub));
List<Pet> copy = new ArrayList<Pet>(pets);
sub = Arrays.asList(pets.get(1), pets.get(4));
System.out.println("sub: " + sub);
copy.retainAll(sub); // 交集操作,保留了所有同时只copy和sub的元素
System.out.println("13: " + copy);
copy = new ArrayList<Pet>(pets);
copy.remove(2);
System.out.println("14: " + copy);
copy.removeAll(sub); // 只移除存在的objects
System.out.println("15: " + copy);
copy.set(1, new Mouse()); //重新设置
System.out.println("16: " + copy);
copy.addAll(2, sub);//插入一个list
System.out.println("17: " + copy);
System.out.println("18: " + pets.isEmpty());
pets.clear();
System.out.println("19: " + pets);//[]
System.out.println("20: " + pets.isEmpty());
pets.addAll(Pets.arrayList(4));
System.out.println("21: " + pets);
Object[] o = pets.toArray();
System.out.println("22: " + o[3]);
// toArray方法 将任意collection 转化为数组。是重载方法。
// 无参数版本 返回Object数组
// 但如果向这个重载版本传递目标类型的数据,它将产生指定类型的数据(假设它能通过类型检查)。
// 如果参数数组太小,存放不下List中所有元素,toArray方法将创建一个具有合适尺寸的数组。
Pet[] pa = pets.toArray(new Pet[0]);
System.out.println("23: " + pa[3].id());// pet对象的id方法
}
}
/*
1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug]
2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster]
3: true
4: Cymric 2
5: -1
6: false
7: true
8: [Rat, Manx, Mutt, Pug, Cymric, Pug]
9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug]
sublist: [Manx, Mutt, Mouse]
10: true
sorted sublist: [Manx, Mouse, Mutt]
11: true
12: true
sub: [Mouse, Pug]
13: [Mouse, Pug]
14: [Rat, Mouse, Mutt, Pug, Cymric, Pug]
15: [Rat, Mutt, Cymric, Pug]
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
*/
作业5
package chapter11holding.e5;
import java.util.*;
public class ListFeatures {
public static void main(String[] args) {
Random rand = new Random(47);
// List<Integer> integers1 = Arrays.asList(1,2,3,4,5);
// System.out.println("1: " + integers1);
// integers1.add(2);
// Arrays.asList()会返回一个ArrayList,
// 但是要特别注意,这个ArrayList是Arrays类的静态内部类,并不是java.util.ArrayList类。
// java.util.Arrays.ArrayList类实现了set(),get(),contains()方法,
// 但是并没有实现增加元素的方法(事实上是可以调用add方法,但是没有具体实现,
// 仅仅抛出UnsupportedOperationException异常),
// 因此它的大小也是固定不变的。
List<Integer> integers = new ArrayList<Integer>(Arrays.asList(6,7,8,9,10));
System.out.println("1: " + integers);
Integer h = new Integer(11);
// Integer h = 11;
integers.add(h); //自动调整size
System.out.println("2: " + integers);
System.out.println("3: " + integers.contains(h));
integers.remove(h); //自动装箱,注意 是remove object 还是 还是 remove Integer.valueOf(2)
Integer p = integers.get(2);
System.out.println("4: " + p + " " + integers.indexOf(p));
Integer q = new Integer(12);
System.out.println("5: " + integers.indexOf(q));
System.out.println("6: " + integers.remove(q));
System.out.println("7: " + integers.remove(p));
System.out.println("8: " + integers);
integers.add(3, new Integer(13));
System.out.println("9: " + integers);
List<Integer> sub = integers.subList(1, 4);
System.out.println("sublist: " + sub);
System.out.println("10: " + integers.containsAll(sub));
Collections.sort(sub);//In-place sort
System.out.println("sorted sublist: " + sub);
System.out.println("11: " + integers.containsAll(sub));// containsAll 与顺序无关
Collections.shuffle(sub, rand);
System.out.println("12: " + integers.containsAll(sub));
List<Integer> copy = new ArrayList<Integer>(integers);
sub = Arrays.asList(integers.get(1), integers.get(4));
System.out.println("sub: " + sub);
copy.retainAll(sub); // 交集操作,保留了所有同时只copy和sub的元素
System.out.println("13: " + copy);
copy = new ArrayList<Integer>(integers);
copy.remove(2);
System.out.println("14: " + copy);
copy.removeAll(sub); // 只移除存在的objects
System.out.println("15: " + copy);
copy.set(1, new Integer(14)); //重新设置
System.out.println("16: " + copy);
copy.addAll(2, sub);//插入一个list
System.out.println("17: " + copy);
System.out.println("18: " + integers.isEmpty());
integers.clear();
System.out.println("19: " + integers);//[]
System.out.println("20: " + integers.isEmpty());
integers.addAll(Arrays.asList(15,16,17));
System.out.println("21: " + integers);
Object[] o = integers.toArray();
System.out.println("22: " + o[2]);
// // toArray方法 将任意collection 转化为数组。是重载方法。
// // 无参数版本 返回Object数组
// // 但如果向这个重载版本传递目标类型的数据,它将产生指定类型的数据(假设它能通过类型检查)。
// // 如果参数数组太小,存放不下List中所有元素,toArray方法将创建一个具有合适尺寸的数组。
//
Integer[] pa = integers.toArray(new Integer[0]);
System.out.println("23: " + pa[2]);// pet对象的id方法
}
}
/*
1: [6, 7, 8, 9, 10]
2: [6, 7, 8, 9, 10, 11]
3: true
4: 8 2
5: -1
6: false
7: true
8: [6, 7, 9, 10]
9: [6, 7, 9, 13, 10]
sublist: [7, 9, 13]
10: true
sorted sublist: [7, 9, 13]
11: true
12: true
sub: [9, 10]
13: [9, 10]
14: [6, 9, 13, 10]
15: [6, 13]
16: [6, 14]
17: [6, 14, 9, 10]
18: false
19: []
20: true
21: [15, 16, 17]
22: 17
23: 17
*/
作业6
package chapter11holding.e6;
import java.util.*;
public class ListFeatures {
public static void main(String[] args) {
Random rand = new Random(47);
List<String> strings = new ArrayList<String>(Arrays.asList("A", "B", "C", "D", "E", "F", "G"));
System.out.println("1: " + strings);
String h = "H";
strings.add(h); //自动调整size
System.out.println("2: " + strings);
System.out.println("3: " + strings.contains(h));
strings.remove(h); //自动装箱,注意 是remove object 还是 还是 remove String.valueOf(2)
String p = strings.get(2);
System.out.println("4: " + p + " " + strings.indexOf(p));
String q = "G";
System.out.println("5: " + strings.indexOf(q));
System.out.println("6: " + strings.remove(q));
System.out.println("7: " + strings.remove(p));
System.out.println("8: " + strings);
strings.add(3, "H");
System.out.println("9: " + strings);
List<String> sub = strings.subList(1, 4);
System.out.println("sublist: " + sub);
System.out.println("10: " + strings.containsAll(sub));
Collections.sort(sub);//In-place sort
System.out.println("sorted sublist: " + sub);
System.out.println("11: " + strings.containsAll(sub));// containsAll 与顺序无关
Collections.shuffle(sub, rand);
System.out.println("12: " + strings.containsAll(sub));
List<String> copy = new ArrayList<String>(strings);
sub = Arrays.asList(strings.get(1), strings.get(4));
System.out.println("sub: " + sub);
copy.retainAll(sub); // 交集操作,保留了所有同时只copy和sub的元素
System.out.println("13: " + copy);
copy = new ArrayList<String>(strings);
copy.remove(2);
System.out.println("14: " + copy);
copy.removeAll(sub); // 只移除存在的objects
System.out.println("15: " + copy);
copy.set(1, "I"); //重新设置
System.out.println("16: " + copy);
copy.addAll(2, sub);//插入一个list
System.out.println("17: " + copy);
System.out.println("18: " + strings.isEmpty());
strings.clear();
System.out.println("19: " + strings);//[]
System.out.println("20: " + strings.isEmpty());
strings.addAll(Arrays.asList("A","B","C","D"));
System.out.println("21: " + strings);
Object[] o = strings.toArray();
System.out.println("22: " + o[3]);
// // toArray方法 将任意collection 转化为数组。是重载方法。
// // 无参数版本 返回Object数组
// // 但如果向这个重载版本传递目标类型的数据,它将产生指定类型的数据(假设它能通过类型检查)。
// // 如果参数数组太小,存放不下List中所有元素,toArray方法将创建一个具有合适尺寸的数组。
//
String[] pa = strings.toArray(new String[0]);
System.out.println("23: " + pa[3]);// pet对象的id方法
}
}
/*
1: [6, 7, 8, 9, 10]
2: [6, 7, 8, 9, 10, 11]
3: true
4: 8 2
5: -1
6: false
7: true
8: [6, 7, 9, 10]
9: [6, 7, 9, 13, 10]
sublist: [7, 9, 13]
10: true
sorted sublist: [7, 9, 13]
11: true
12: true
sub: [9, 10]
13: [9, 10]
14: [6, 9, 13, 10]
15: [6, 13]
16: [6, 14]
17: [6, 14, 9, 10]
18: false
19: []
20: true
21: [15, 16, 17]
22: 17
23: 17
*/
作业7
package chapter11holding.e7;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class IDClass {
private static int counter;
private int count = counter++;
public String toString() {
return "IDClass " + count;
}
}
public class E7 {
public static void main(String[] args) {
IDClass[] idc = new IDClass[10];
for (int i = 0; i < 10; i++) {
idc[i] = new IDClass();
}
List<IDClass> idClasses = new ArrayList<IDClass>(Arrays.asList(idc));
System.out.println(idClasses);
List<IDClass> sublist = idClasses.subList(3, 5);
System.out.println(sublist);
sublist.removeAll(sublist);
System.out.println(idClasses);
}
}
11.6 迭代器
package chapter11holding;
import typeinfo.pets.Pet;
import typeinfo.pets.Pets;
import java.util.Iterator;
import java.util.List;
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.println(p.id() + ": " + p + " ");
}
System.out.println();
// 若可以的话,一种简单方法approach
for(Pet p : pets)
System.out.println(p.id() + ": " + p + " ");
System.out.println(pets);
it =pets.iterator();
//Iterator 还可以移除由next产生的最后一个元素,意味着 在调用remove()之前必须先调用next()
for (int i = 0; i< 6; i++){
it.next();
it.remove();
}
System.out.println(pets);
}
}
package chapter11holding.e8;
import java.util.ArrayList;
import java.util.Iterator;
class Gerbil { // 沙鼠
private static int counter;
private final int gerbilNumber = counter++;
void hop() {
System.out.println(this +" gerbilNumber :" + gerbilNumber + " hop()");
}
}
public class E8 {
public static void main(String[] args) {
ArrayList<Gerbil> gerbils = new ArrayList<Gerbil>();
for (int i = 0; i < 3; i++)
gerbils.add(new Gerbil());
Iterator<Gerbil> gerbilIterator = gerbils.iterator();
while (gerbilIterator.hasNext()){
Gerbil gerbil = gerbilIterator.next();
gerbil.hop();
}
}
}
/*
chapter11holding.e8.Gerbil@5e481248 gerbilNumber :0 hop()
chapter11holding.e8.Gerbil@66d3c617 gerbilNumber :1 hop()
chapter11holding.e8.Gerbil@63947c6b gerbilNumber :2 hop()
*/
package chapter11holding.e9;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Sequence {
private Object[] items;
private int next = 0;
public Sequence(int size) {
items = new Object[size];
}
public void add(Object x) {
if (next < items.length)
items[next++] = x;
}
private class SequenceSelector implements Iterator {
private int i = 0;
@Override
public boolean hasNext() {
return i < items.length;
}
@Override
public Object next() {
if (hasNext()) return items[i++];
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
}
public Iterator iterator() {
return new SequenceSelector();
}
public static void main(String[] args) {
Sequence sequence = new Sequence(10);
for (int i = 0; i < 10; i++)
sequence.add(Integer.toString(i));
for (Iterator it = sequence.iterator(); it.hasNext(); ) {
System.out.println(it.next() + " ");
}
}
}
package chapter11holding.e10;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
class Rodent{
void eat() {
System.out.println("Rodent.eat()");
}
}
class Mouse extends Rodent {
void eat() {
System.out.println("Mouse.eat()");
}
}
class Gerbil extends Rodent { // 鼹鼠
void eat() {
System.out.println("Gerbil.eat()");
}
}
class Hamste extends Rodent { // 大颊鼠
void eat() {
System.out.println("Hamste.eat()");
}
}
public class E09_Rodent {
public static void main(String[] args) {
ArrayList<Rodent> rodentArrayList = new ArrayList<Rodent>(Arrays.asList(new Mouse(),
new Gerbil(),
new Hamste()));
Rodent r;
for (Iterator<Rodent> it = rodentArrayList.iterator(); it.hasNext(); ) {
r = it.next();
r.eat();
System.out.println(r);
}
}
}
作业11
没看明白
package chapter11holding.e11;
import chapter11holding.e4.MovieNameGenerator;
import java.util.*;
public class E11 {
public static void printToString(Iterator<?> it){
while (it.hasNext())
System.out.println(it.next().toString());
}
public static void main(String[] args) {
List<Collection<String>> ca = Arrays.<Collection<String>>asList(
new ArrayList<>(),
new LinkedList<>(),
new HashSet<>(),
new TreeSet<>()
);
for(Collection<String> c: ca)
MovieNameGenerator.fill(c);
for(Collection<String> c: ca)
printToString(c.iterator());
}
}
11.6.1 ListIterator
package java.util;
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext(); //检查是否有下一个元素
E next(); //返回下一个元素
boolean hasPrevious(); //check是否有previous(前一个)element(元素)
E previous(); //返回previous element
int nextIndex(); //返回下一element的Index
int previousIndex(); //返回当前元素的Index
void remove(); //移除一个elment
void set(E e); //set()方法替换访问过的最后一个元素 注意用set设置的是List列表的原始值
void add(E e); //添加一个element
}
package chapter11holding;
import typeinfo.pets.Pet;
import typeinfo.pets.Pets;
import java.util.List;
import java.util.ListIterator;
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.println(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); // 从index 开始遍历,替换从位置3开始向前的所有Pet对象
while (it.hasNext()) {
it.next();
it.set(Pets.randomPet());
}
System.out.println(pets);
}
}
/*
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]
*/
作业12
package chapter11holding.e12;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.*;
public class E12{
static void reverse(List<Integer> list) {
ListIterator<Integer> fwd = list.listIterator();
ListIterator<Integer> rev =
list.listIterator(list.size()); //这里将rev指向了List的最后一个元素
int mid = list.size() >> 1;
for(int i = 0; i < mid; i++) { // 有意思
Integer tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp); }
}
public static void main(String[] args) {
List<Integer> src =
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> dest = new LinkedList<Integer>(src);
System.out.println("source: " + src);
System.out.println("destination: " + dest);
reverse(dest);
System.out.println("source: " + src);
System.out.println("destination: " + dest);
}
}/* output:
source: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
destination: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
source: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
destination: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
*/
11.7 LinkedList
/**
* getFirst()和element()完全一样,它们都返回列表的头(第一个元素),而不是移除它,如果List为空,则抛出NoSuchElementException.
* public E element() {
* return getFirst();
* }
*
* public E getFirst() {
* final Node<E> f = first;
* if (f == null)
* throw new NoSuchElementException();
* return f.item;
* }
*
* peek()方法与这两个方式只是稍有差异,它在列表为空时返回null
* public E peek() {
* final Node<E> f = first;
* return (f == null) ? null : f.item;
* }
*
*
* removeFirst()与remove()也是完全一样,它们移除并返回列表的头,而在列表为空时抛出NoSuchElementException.
* public E remove() {
* return removeFirst();
* }
*
* public E removeFirst() {
* final Node<E> f = first;
* if (f == null)
* throw new NoSuchElementException();
* return unlinkFirst(f);
* }
*
* poll()稍有差异,它在列表为空时返回null
* public E poll() {
* final Node<E> f = first;
* return (f == null) ? null : unlinkFirst(f);
* }
*
* addFirst(),offer()和addList()相同,它们都将某个元素插入到列表的尾(端)部.
* public void addFirst(E e) {
* linkFirst(e);
* }
* public boolean offer(E e) {
* return add(e);
* }
* public boolean add(E e) {
* linkLast(e);
* return true;
* }
*
*
* removeLast()移除并返回列表的最后一个元素
* public E removeLast() {
* final Node<E> l = last;
* if (l == null)
* throw new NoSuchElementException();
* return unlinkLast(l);
* }
*/
package chapter11holding;
import typeinfo.pets.*;
import java.util.LinkedList;
import static net.mindview.util.Print.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());
// 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());
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());
}
}
/*
[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
*/
作业13
package chapter11holding.e13.controller;
// 控制系统的可重用的框架
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Controller {
private LinkedList<Event> eventlist = new LinkedList<Event>();
public void addEvent(Event c) {
eventlist.add(c);
}
public void run() {
Iterator<Event> it = new LinkedList<Event>(eventlist).iterator();
// Iterator<Event> it = eventlist.iterator();
while (it.hasNext()){
Event event= it.next();
if (event.ready()){
System.out.println(event);
event.action();
eventlist.remove(event);
}
}
// eventlist1 = new LinkedList<Event>(eventlist);
// Iterator<Event> it = eventlist1.iterator();
//// Iterator<Event> it = eventlist.iterator();
// while (it.hasNext()){
// Event event= it.next();
// if (event.ready()){
// System.out.println(event);
// event.action();
// eventlist.remove(event);
// System.out.println(eventlist.size());
// System.out.println(eventlist1.size());
// }
// }
// while (eventlist.size() > 0)
// //对eventList做一个拷贝,免得改动了原来的数据
// for(Event e: new ArrayList<Event>(eventlist))
// if (e.ready()){
// System.out.println(e);
// e.action();
// eventlist.remove(e);
// }
}
}
作业14
package chapter11holding.e14;
import java.util.LinkedList;
import java.util.ListIterator;
public class E14 {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<Integer>();
ListIterator it = linkedList.listIterator();
for (int i = 1; i <= 10; i++) {
it.add(i);
if (i % 2 == 0)
it.previous();
}
System.out.println(linkedList);
}
}
/*
[1, 3, 5, 7, 9, 10, 8, 6, 4, 2]
*/
11.8 Stack
"Stack" 通常时指"后进后出"(LIFO)的容器,有时栈也被称为叠加栈,因为最后"压入"栈的元素,第一个"弹出"栈
package chapter11holding;
import net.mindview.util.Stack; // 使用的是java编程思想的栈 LinkedList实现
public class StackTest{
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
for (String s: "My dog has fleas".split(" "))
stack.push(s);
while (!stack.empty())
System.out.print(stack.pop()+ " ");
}
}
/* Output
fleas has dog My
*/
编程思想的Stack和java的Stack使用实例
package chapter11holding;
import net.mindview.util.Stack;
public class StackCollision {
public static void main(String[] args) {
Stack<String> stack =
new 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() + " ");
}
}
/*
fleas has dog My
fleas has dog My
*/
作业15
package chapter11holding.e15;
import net.mindview.util.Stack;
public class E15 {
private final static Stack<Character> stack = new Stack<Character>();
public static void evaluator(String expr) {
char data[] = expr.toCharArray();
for (int i = 0; i < data.length; )
switch (data[i++]) {
case '+':
stack.push(data[i++]);
break;
case '-':
System.out.print(stack.pop());
}
}
private final static Stack<String> stack2 = new Stack<String>();
public static void evaluator2(String expr) {
String[] s = expr.split("");
for (int i = 0; i < s.length; i++) {
if (s[i].equals("+")) {
stack2.push(s[++i]);
} else if (s[i].equals("-")) {
System.out.print(stack2.pop());
}
}
}
public static void main(String[] args) {
String s = "+U+n+c---+e+r+t---+a-+i-+n+t+y---+ -+r+u--+l+e+s---";
evaluator(s);
System.out.println();
evaluator2(s);
}
}
11.9 Set
HashSet 散列
TreeSet 元素存储在红--黑树数据结构
LinkedSet 出于速度原因也使用了散列,但看起来它使用了链表来维护元素的插入顺序
HashSet无序,是指 存储元素的顺序并不是按照存入时的顺序
打印是无序,
实际jdk8已排序
package chapter11holding;
import java.util.HashSet;
import java.util.Random;
public class SetOfInteger {
public static void main(String[] args) {
// Random rand = new Random(new Date().getTime());
Random rand = new Random(17);
HashSet<Integer> intset = new HashSet<Integer>();
for(int i = 0; i < 1000; i++) {
intset.add(rand.nextInt(30));
}
System.out.println(intset);//0~29之间的数出现了10000次但每一个数只有一个出现在结果中
}
}
*/
产生的元素都是唯一的列表
package chapter11holding;
import net.mindview.util.TextFile;
import java.util.Set;
import java.util.TreeSet;
public class UniqueWords {
public static void main(String[] args) {
// \W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
Set<String> words = new TreeSet<String>(new TextFile("/Users/erin/JavaProject/thinking_in_java_example/src/main/java/chapter11holding/SetOperations.java", "\\W+"));
System.out.println(words);
}
}
package chapter11holding;
import net.mindview.util.TextFile;
import java.util.Set;
import java.util.TreeSet;
public class UniqueWordsAlphabetic {
public static void main(String[] args) {
// public TreeSet(Comparator<? super E> comparator) {
// this(new TreeMap<>(comparator));
// }
Set<String> words = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); // 不区分大小写排序
words.addAll(new TextFile("/Users/erin/JavaProject/thinking_in_java_example/src/main/java/chapter11holding/SetOperations.java","\\W+"));
System.out.println(words);
}
}
/*
[A, add, addAll, added, args, B, C, chapter11holding, class, Collections, contains, containsAll, D, E, F, from, G, H, HashSet, I, import, in, J, java, K, L, M, main, N, new, out, package, println, public, remove, removeAll, removed, Set, set1, set2, SetOperations, split, static, String, System, to, util, void, x, y, z]
*/
package chapter11holding.e16;
import net.mindview.util.TextFile;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class E16 {
private final static Set<Character> vowels = new HashSet<Character>(Arrays.asList('a','e','u','i','o','A','E','U','I','O'));
public static void main(String[] args) {
Set<String> strings = new TreeSet<String>();
int fileVowels =0;
int wordVowels;
for(String s :new TextFile("/Users/erin/JavaProject/thinking_in_java_example/src/main/java/chapter11holding/UniqueWords.java","\\W+"))
{
wordVowels = 0;
for(char letter:s.toCharArray())
if (vowels.contains(letter))
wordVowels++;
if(!strings.contains(s)){
strings.add(s);
System.out.println(s + " has " + wordVowels + " vowel(s)");
}
fileVowels += wordVowels;
}
System.out.println("Total number of vowels in file : " + fileVowels);
}
}
11.10 Map
Map.一组成对的"键值对"对象,允许你使用键来查找值,ArrayList允许你使用数字来查找值,因此在某种意义上讲,它将数字与对象关联在了一起.映射表允许我们使用另一个对象,它也被称为"关联数组",因为它将某些对象与另外一些对象关联在了一起,或者被称为"字典",因为你可以使用键对象来查找值对象,就像在字典中使用单词来定义一样,Map是强大的编程工具
将对象映射到其它对象的能力是一种解决编程问题的杀手锏,例如考虑一个程序,它将接受来自Java的Random类到随机性,在理想状态下,Random可以产生理想的数字分布,但要向测试它,则需要产生大量的随机数,不对落入各种不同范围的数字进行计数,Map很容易可以解决该问题
package chapter11holding;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
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 < 1000; i++){
int r = rand.nextInt(30);
Integer freq = m.get(r);
m.put(r,freq == null ? 0: freq+1); // 键不在容器返回Null,该数字第一次被找到, freq+1 自动包装机制
}
System.out.println(m);
}
}
下列示例演示了String
package chapter11holding;
import typeinfo.pets.*;
import java.util.HashMap;
import java.util.Map;
public class PetMap {
public static void main(String[] args) {
Map<String, Pet> petMap = new HashMap<String, Pet>();
petMap.put("My Cat",new Cat("Molly"));
petMap.put("My Dog",new Dog("Ginger"));
petMap.put("My Hamster",new Hamster("Bosco"));
System.out.println(petMap);
Pet dog = petMap.get("My Dog");
System.out.println(dog);
System.out.println(petMap.containsKey("My Dog"));
System.out.println(petMap.containsValue(dog));
}
}
/*
{My Dog=Dog Ginger, My Cat=Cat Molly, My Hamster=Hamster Bosco}
Dog Ginger
true
true
*/
map可以很容易扩展到多维,而我们只需要将其值设置为map(这些Map的值可以是其它容器,甚至是map),因此我们能很容易将容器组合起来从而快速生成强大的数据结构,下面是一个示例
package chapter11holding;
import typeinfo.pets.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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) {
System.out.println("People: " + petPeople.keySet());// 所有的键组成的Set
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);
}
}
}
Queue
队列是一个典型的先进先出(FIFO)的容器,即从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序是相同的,队列常常被当作一种可靠的对象从程序的某个区域传输到另一个区域,队列在并发编程中特别重要
package chapter11holding;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class QueueDemo {
public static void printQ(Queue queue) {
while(queue.peek() != null) // peek 和 element都在不移除的情况下返回对头,但peek在对列为空时,返回null
System.out.print(queue.remove() + " ");// poll 和remove 都移除并返回队头,但poll在对列空时,返回null,remove会抛出异常
System.out.println();
}
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<Integer>();// Linkedlist 向上转型为Queue
Random rand = new Random(47);
for(int i = 0; i < 10; i++)
queue.offer(rand.nextInt(i + 10)); // 自动包装机制 将 int转换为Integer
printQ(queue);
Queue<Character> qc = new LinkedList<Character>();
for(char c : "Brontosaurus".toCharArray())
qc.offer(c);//// 自动包装机制 将 char 转换为Character
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
*///:~
作业27
package chapter11holding.e27;
import chapter9interfaces.interfaceprocessor.Processor;
import java.util.LinkedList;
import java.util.Queue;
class Command {
private String cmd;
Command(String cmd) {
this.cmd = cmd;
}
public void operation() {
System.out.println("string : " + cmd);
}
}
class Producer {
public static void produce(Queue<Command> q) {
q.offer(new Command("load"));
q.offer(new Command("delete"));
q.offer(new Command("save"));
}
}
class Consumer {
public static void comsume(Queue<Command> q) {
while (q.peek() != null)
q.remove().operation();
}
}
public class E27 {
public static void main(String[] args) {
Queue<Command> cmds = new LinkedList<Command>();
Producer.produce(cmds);
Consumer.comsume(cmds);
}
}
PriorityQueue(优先级队列)
先进先出声明的是下一个元素应该是等待时间最长的元素
优先级队列声明下一个弹出的元素是最需要的元素(具有最高优先级),当在PriorityQueue调用offer()方法插入一个对象时,这个对象就会在队列中被排序,默认的排序将使用队列中的自然排序,但是可以通过提供自己的Comparator来修改这个顺序,PriorityQueue可以确保当你调用peek(),poll()和remove()方法时,获得的元素将是队列优先级最高的元素,
package chapter11holding;
import java.util.*;
public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue =
new PriorityQueue<Integer>();
Random rand = new Random(47);
for(int i = 0; i < 10; i++)
priorityQueue.offer(rand.nextInt(i + 10));
QueueDemo.printQ(priorityQueue);
List<Integer> ints = Arrays.asList(25, 22, 20,
18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25);
priorityQueue = new PriorityQueue<Integer>(ints);
QueueDemo.printQ(priorityQueue);
priorityQueue = new PriorityQueue<Integer>(
ints.size(), Collections.reverseOrder());
priorityQueue.addAll(ints);
QueueDemo.printQ(priorityQueue);
String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION";
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());//Collections.reverseOrder()反序排列
stringPQ.addAll(strings);
QueueDemo.printQ(stringPQ);
Set<Character> charSet = new HashSet<Character>();
for(char c : fact.toCharArray())
charSet.add(c); // Autoboxing
PriorityQueue<Character> characterPQ =
new PriorityQueue<Character>(charSet);
QueueDemo.printQ(characterPQ);
}
}
/*
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
A A B C C C D D E E E F H H I I L N N O O O O S S S T T U U U W
W U U U T T S S S O O O O N N L I I H H F E E E D D C C C B A A
A B C D E F H I L N O S T U W
*/
作业28
package chapter11holding.e28;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
public class E28 {
public static void printQ(Queue<?> queue) {
while (queue.peek() != null)
System.out.print(queue.poll() + " ");
System.out.println();
}
public static void main(String[] args) {
Random rand = new Random(47);
PriorityQueue<Double> pq = new PriorityQueue<Double>();
for (int i = 0; i < 10; i++)
pq.offer(rand.nextDouble());
printQ(pq);
}
}
作业29
package chapter11holding.e29;
import java.util.PriorityQueue;
class Dummy{}
public class E29 {
public static void main(String[] args) {
PriorityQueue<Dummy> queue = new PriorityQueue<Dummy>();
queue.offer(new Dummy());
queue.offer(new Dummy());// 第二次插入将引发异常 ClassCastException
}
}
Collection 和 Iteration
Collection是描述所有 序列容器的共性的根接口,它可以被认为是一个"附属接口",即因为要表示其他若干个接口的共性而出现的接口,另外,java.uitl.AbstaractCollection类提供了Collection的默认实现,使得你可以创建AbstractCollection的子类型,而其中没有不必要的重复
使用接口描述的一个理由是它可以使我们能够创建更通用的代码,通过针对接口而非具体实现来编写代码,我们的代码可以应用于任何实现了Collection的类--这也就使得一个新类可以选择去实现Collection接口,以便我们可以使用它
package chapter11holding;
import typeinfo.pets.Pet;
import typeinfo.pets.Pets;
import java.util.*;
public class InterfaceVsIterator {
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 display(Collection<Pet> pets) {
for(Pet p : pets)
System.out.print(p.id() + ":" + p + " ");
System.out.println();
}
public static void main(String[] args) {
List<Pet> petList = Pets.arrayList(8);
Set<Pet> petSet = new HashSet<Pet>(petList);
Map<String,Pet> petMap =
new LinkedHashMap<String,Pet>();
String[] names = ("Ralph, Eric, Robin, Lacey, " +
"Britney, Sam, Spot, Fluffy").split(", ");
for(int i = 0; i < names.length; i++)
petMap.put(names[i], petList.get(i));
display(petList);
display(petSet);
display(petList.iterator());
display(petSet.iterator());
System.out.println(petMap);
System.out.println(petMap.keySet());
display(petMap.values());
display(petMap.values().iterator());
}
}
/*
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
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
{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy]
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
*/
Foreach与迭代器
foreach语法主要用于数组,但是它也可以用于Collection对象
package chapter11holding;
import java.util.*;
public class ForEachCollections {
public static void main(String[] args) {
Collection<String> cs = new LinkedList<String>();
Collections.addAll(cs,
"Take the long way home".split(" "));
for(String s : cs) // foreach
System.out.print("'" + s + "' ");
}
}
cs是一个Colllection,所以这段代码展示了能够与foreach一起工作是所有Collection对象的特性
之所以能够工作,是因为Iterable接口,该接口包含了一个能够产生Iterator的iterator()方法,并且Iterator接口被foreach用来在序列中移动,因此如果你创建了任何实现了Iterable的类,都可以用于foreach语句中:
package chapter11holding;
import java.util.Iterator;
public class IterableClass implements Iterable<String> {
protected String[] words = ("And that is how " +
"we know the Earth to be banana-shaped.").split(" ");
@Override
public Iterator<String> iterator() {//返回匿名内部类Iterator<String>的实例,该匿名内部类可以遍历数组中的所有单词
return new Iterator<String>() {
private int index = 0;
public boolean hasNext() {
return index < words.length;
}
public String next() { return words[index++]; }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
for(String s : new IterableClass())(//foreach语句调用了Iterator的方法
System.out.print(s + " ");
}
}
package chapter11holding;
import java.util.Map;
public class EnvironmentVariables {
public static void main(String[] args) {//System.getenv()返回一个Map,entrySet()产生一个
//Map.Entry的元素构成的Set,并且这个Set是一个Iterable,因此它可以用于foreach循环
for(Map.Entry entry:System.getenv().entrySet())
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
package chapter11holding;
import java.util.Arrays;
public class ArrayIsNotIterable {
static <T> void test(Iterable<T> ib){
for (T t: ib)
System.out.println(t +" ");
}
public static void main(String[] args) {
test(Arrays.asList(1,2,3));
String[] strings = {"A","B","C"};
// test(strings); // 数组到Iterable需要手工转换
test(Arrays.asList(strings));
}
}
作业31
package chapter11holding.e31;
import chapter8polymorphism.Shape.Circle;
import chapter8polymorphism.Shape.Shape;
import chapter8polymorphism.Shape.Square;
import chapter8polymorphism.Shape.Triangle;
import java.util.Iterator;
import java.util.Random;
public class RandomShapeGenerator implements Iterable<Shape> { // Iterable<Shape>
private Random random = new Random(47);
private static int count;
public Shape nextShape() {
switch (random.nextInt(3)) {
default:
case 0:
return new Circle();
case 1:
return new Square();
case 2:
return new Triangle();
}
}
public RandomShapeGenerator(int count) {
this.count = count;
}
@Override
public Iterator<Shape> iterator() { //Iterable<Shape>
return new Iterator<Shape>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < count;
}
@Override
public Shape next() {
index++;
return nextShape();
}
};
}
public static void main(String[] args) {
RandomShapeGenerator rsg = new RandomShapeGenerator(5);
for (Shape s : rsg)
System.out.println(s.getClass().getSimpleName());
}
}
java adapter(适配器)惯用方法
如果现在有一个Iterable类,你想要添加一种或多种在foreach语句中使用这个类的方法,例如方向迭代,应该怎么做呢? 如果之间继承这个类,并且覆盖iterator()方法,你只能替换现有的方法,而不能实现选择
一种解决方案是所谓的adapter方法的惯用法,"适配器"部分来自于设计模式,因为你必须提供特定接口以满足foreach语句,当你有一个接口并需要另一个接口时,编写adapter就可以解决问题,这里,希望在默认的前向迭代器的基础上,添加方向迭代器的能力,因此不能使用覆盖,而是添加了一个能够产生Iterable对象的方法,该对象可以用于foreach语句,正如你所见,可以提供多种使用foreach的方式
package chapter11holding;
// The "Adapter Method" idiom allows you to use foreach
// with additional kinds of Iterables.
import java.util.*;
class ReversibleArrayList<T> extends ArrayList<T> {
public ReversibleArrayList(Collection<T> c) { super(c); }
public Iterable<T> reversed() {//返回一个具有反向迭代器的Iterable
return new Iterable<T>() {
public Iterator<T> iterator() {
return new Iterator<T>() {
int current = size() - 1;
public boolean hasNext() { return current > -1; }
public T next() { return get(current--); }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
};
}
}
public class AdapterMethodIdiom {
public static void main(String[] args) {
ReversibleArrayList<String> ral =
new ReversibleArrayList<String>(
Arrays.asList("To be or not to be".split(" ")));
// Grabs the ordinary iterator via iterator():
for(String s : ral)
System.out.print(s + " ");
System.out.println();
// Hand it the Iterable of your choice
for(String s : ral.reversed())
System.out.print(s + " ");
}
} /* Output:
To be or not to be
be to not or be To
*///:~
package chapter11holding;
import java.util.*;
public class MultiIterableClass extends IterableClass {
public Iterable<String> reversed() {
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
int current = words.length - 1;
@Override
public boolean hasNext() {
return current > -1;
}
@Override
public String next() {
return words[current--];
}
};
}
};
}
public Iterable<String> randomized(){
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
List<String> shuffled = new ArrayList<String>(Arrays.asList(words));
Collections.shuffle(shuffled,new Random(47));
return shuffled.iterator();
}
};
}
public static void main(String[] args) {
MultiIterableClass mic = new MultiIterableClass();
for (String s: mic.reversed())
System.out.print(s + " ");
System.out.println();
for (String s: mic.randomized())
//Collections方法并没有打乱原来的数组,而是打乱了shuffled中的引用,
// 之所以这样,只是因为,randmize()方法用一个ArrayList将Arrays.asList()结果包装了起来
System.out.print(s + " ");
System.out.println();
for (String s: mic)
System.out.print(s + " ");
System.out.println();
}
}
package chapter11holding;
import java.util.*;
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 };
List<Integer> list1 =
new ArrayList<Integer>(Arrays.asList(ia));//ia的输出被传给了ArrayList构造器,这将创建一个ia的元素引用的ArrayList
System.out.println("Before shuffling: " + list1);
Collections.shuffle(list1, rand);
System.out.println("After shuffling: " + list1);
System.out.println("array: " + Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia);//lsit2 直接使用Arrays.asList(ia),这样做会直接修改ia的数据
System.out.println("Before shuffling: " + list2);
Collections.shuffle(list2, rand);
System.out.println("After shuffling: " + list2);
System.out.println("array: " + Arrays.toString(ia));
}
} /* Output:
Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9]
array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After shuffling: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
*///:~
作业32
package chapter11holding.e32;
import chapter11holding.InterfaceVsIterator;
import typeinfo.pets.Pet;
import typeinfo.pets.Pets;
import java.util.*;
class PetSequence {
protected Pet[] pets = Pets.createArray(8);
}
public class NonCollectionSequence extends PetSequence implements Iterable<Pet>{
public Iterator<Pet> iterator() {
return new Iterator<Pet>() {
private int index = 0;
public boolean hasNext() {
return index < pets.length;
}
public Pet next() {
return pets[index++];
}
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
public Iterable<Pet> reversed() {
return new Iterable<Pet>() {
@Override
public Iterator<Pet> iterator() {
return new Iterator<Pet>() {
private int index = pets.length - 1;
@Override
public boolean hasNext() {
return index > -1;
}
@Override
public Pet next() {
return pets[index--];
}
};
}
};
}
public Iterable<Pet> randomized() {
return new Iterable<Pet>() {
public Iterator<Pet> iterator() {
List<Pet> shuffledd = new ArrayList<Pet>(Arrays.asList(pets));
Collections.shuffle(shuffledd, new Random(47));
return shuffledd.iterator();
}
};
}
public static void main(String[] args) {
NonCollectionSequence nc = new NonCollectionSequence();
for (Pet pet : nc.reversed())
System.out.print(pet + " ");
System.out.println();
for (Pet pet : nc.randomized())
System.out.print(pet + " ");
System.out.println();
for (Pet pet : nc)
System.out.print(pet + " ");
}
}
/*
Manx Pug Cymric Pug Mutt Cymric Manx Rat
Pug Mutt Pug Rat Manx Manx Cymric Cymric
Rat Manx Cymric Mutt Pug Cymric Pug Manx
*/
总结
17章深入