ThinkInJava_11_持有对象(容器)

11.1 泛型和类型安全的容器

import java.util.*;

class Apple {
	private static long counter;
	private final long id = counter++;
	public long id() { return id; }
}
class Orange {}
public class ApplesAndOrangesWithoutGenerics {
	@SuppressWarnings("unchecked") //不受检查的异常的警告信息应该被抑制
	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());
		for(int i = 0;i < apples.size();i++)
			System.out.println(((Apple)apples.get(i)).id());
	}
}
/*
0
1
2
异常
  • 用上泛型避免添加不同类对象的问题
ArrayList<Apple> apples = new ArrayList<Apple>();
//此时从容器中取出对象也不用强制类型转换了,因为通过泛型,编译器知道里面对象的类型
  • 向上转型也可以用于泛型容器
class Gala extends Apple {}
class Fuji extends Apple {}
public Class A {
	public static void main(String[] args) {
		ArrayList<Apple> apples = new ArrayList<Apple>();
		apples.add(new Gala());
		apples.add(new Fuji());
	}
}
  • ArrayList 里直接添加不同类型的对象不会报错,在编译期间和运行时都不会有问题,从 ArrayList 中取出对象只能得到 Object 类型引用,必须强制向下转型

11.2 基本概念

  1. Collection 序列
    2)Map 键值对
  • ArrayList 向上转型为接口 List,使用接口,创建对象可以使用不同实现类
List<Apple> apples = new ArrayList<Apple>();
Collection<Integer> c = new ArrayList<Integer>();
for(int i = 0;i < 10;i++)
	c.add(i);

11.3 添加一组元素

  • 数组可转化成一个 List
  • 一些向 collection 中添加元素的方法
Collection<Integer> collection = 
	new ArrayList<Integer>(Array.asList(1,2,3,4,5));
Integer[] more = { 6,7,8,9,10 };
collection.addAll(Arrays.asList(more));
Collection.addAll(collection,11,12,13,14,15); //首选方式
Collection.addAll(collection,more);
collection.set(1,99);
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) {
		List<Snow> snow1 = 
		Array.asList( new Crusty(), new Slush(), new Powder() );
		List<Snow> snow1 = 
		Array.asList( new Light(), new Heavy() );
		//编译错误,因为Light和Heavy都是Powder类的子类,
		//所以Array.asList()只会创建Powder类的对象,
		//而不会创建Snow类对象,即 ArrayList<Powder>()
	}
}

11.4 容器的打印

  • Collection
 [a, b, c, d]
  • Map
{a=aa, b=bb, c=cc, d=dd}

11.5 List

  • List 承诺可以将元素维护在特定的序列中
  • 1)ArrayList
    1. LinkedList

11.6 迭代器

  • 不关心容器的类型而直接使用不同的容器
  • Java 的容器 Iterator 只能单向移动
    1)使用 Iterator() 返回一个 Iterator,Iterator 将准备返回第一个元素
    2)next()
  1. hasNext()
  2. remove() 删除新近返回的迭代器元素
List<Pet> pets = Pets.arrayList(12);
Iterator<Pet> it = pets.iterator();
while(it.hasNext())
	Pets p = it.next();
it = pets.iterator();
for(int i = 0;i < 6;i++){
	it.next();
	it.remove();
}
  • Iterator 可以用于各种类型的容器遍历
public static void display(Iterator<Pet> iterator) {
	while(iterator.hasNext())
		Pet p = iterator.Next();
}
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());
  • ListIterator 是 Iterator 的子类型,只能用于 List 的遍历, 能够双向移动
ListIterator<Pet> it = pets.listIterator(); //生成 ListIterator
ListIterator<Pet> it = pets.listIterator(3); //指向 3 位置的 ListIterator
it.hasNext()
it.next()
it.nextIndex();
it.previous();
it.hasPrevious();
it.previousIndex();
it.set(Pets.randomPet()); //用新的元素替换当前迭代器中元素

11.7 LinkedList

  • LinkedList 在插入删除方面更高效,在随机访问方面较逊色
ll.getFirst(); //获取首元素,空时抛出异常
ll.element(); //同获取首元素,空时抛出异常
ll.peek(); //首元素,空时返回 null 
ll.remove(); //删除首元素
ll.removeFirst(); //同删除首元素
ll.poll(); //删除首元素,空时返回 null
ll.add(); //插入尾端
ll.addFirst(); //插入首端
ll.addLast(); //插入尾端
ll.offer() //也是插入尾端
ll.removeLast() //移除尾端元素

11.8 Stack

public class Stack<T> {
	private LinkedList<T> storage = new LinkedList<T>();
	public void push(T v) { storage.addFirst(v); }
	public T peek() { return storage.getFirst(); }
	public T pop() { return storage.removeFirst(); }
	public boolean empty() { return storage.isEmpty(); }
	public String toString() { return storage.toString(); }

11.9 Set

  • Set 不保存重复元素
  • Set 实际上就是 Collection,没有任何扩展的方法
SortedSet<Integer> intset = new TreeSet<Integer>();
//TreeSet 是一种有序的 Set
Set<String> words = 
new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
//按字母序排序

11.10 Map

public class PetMap {
	public static void main(String[] args) {
		Map<String,Pet> petMap = new HashMap<String,Pet>();
		petMap.put("Cat",new Cat("dandan"));
		petMap.put("Dog",new Dog("dudu"));
		Pet dog = petMap.get("Dog");
		petMap.containsKey("Dog"); //true
		petMap.containsValue("dudu"); //true
}
  • Map 扩展成多维
Map<Person,List<Pet>> petPeople;
//按 key 值遍历 value
for(Person person : petPeople.keySet()) {
	for(Pet pet : petPeople.get(person)) {}
}

11.11 Queue

  • 可将 LinkedList 向上转型为 Queue
queue.offer(); //元素插入队尾
queue.poll(); //移除队首元素
queue.remove(); //移除队首元素
  • PriorityQueue 优先队列,在 offer() 插入元素时按优先级插入队列,返回队首元素时,将返回优先级最高的元素
PriorityQueue<Integer> priorityQueue = 
new PriorityQueue<Integer>(100,Collections.reverseOrder());
//优先级为降序

11.12 Collection 和 Iterator

  • Java 使用通用的 Collection 接口和迭代器结合的方式,让不同的序列容器实现可以由更通用的代码复用
public class InterfaceVsIterator {
	public static void display(Iterator<Pet> it) {
		while(it.hasNext())
			Pet pet = it.next();
	}
	public static void display(Collection<Pet> pets) {
		for(Pet pet : pets)
			print(p.id());
	}
}
//用两种方式都可以将容器的遍历与底层容器的特定实现解藕
  • AbstractCollection 类提供了 Collection 的默认实现,可以直接创建 AbstractCollect 的子类型
public class CollectionSquence
extends AbstractCollection<Pet> { //AbstractColletion 类必须实现 iterator() 方法和 size() 方法
	private Pet[] pets = Pets.createArray(8);
	public int size() { return pets.length; }
	//用匿名内部类实现 iterator() 方法
	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() {}
		}
	}
}

11.13 Foreach 与迭代器

  • Collection 的任何实现类都能使用 foreach() 语法,因为引入了 Iterable 的接口,包含一个能够产生 Iterator 的 iterator() 方法
  • Map 的 entrySet() 方法也是一个 Set,也是一个 Iterable
public class EnvironmentVariables {
	public static void main(String[] args) {
		for(Map.Entry entry : System.getenv().entrySet()) {
			System.out.println(entry.getKey() + ": " + 
				entry.getValue());
		}
	}
}
  • 数组可以使用 foreach() 语法,但数组并不是 Iteratable
import java.util.*;

class ReversibleArrayList<T> extends ArrayList<T> {
	public ReversibleArrayList(Collection<T> c) { super(c); }
	public Iterable<T> reversed() {
		return new Iterable<T>() {
			public Iterable<T> iterator() {
				return new Iterable<T>() {
					int current = size() - 1;
					public boolean hasNext() { return current > -1; }
					public T next() { return get(current--); }
					public void remove() {}
				};
			}
			
		};
	}
}

public class AdapterMethodIdiom {
	public static void main(String[] args) {
		ReversibleArrayList<String> ral = 
			new ReversibleArrayList<String>(
				Arrays.asList("To be or not to be".split(" ")));
		for(String s : ral)
			System.out.print(s + " ");
		System.out.println();
		for(String s : ral.reversed())
			System.out.print(s + " ");
		System.out.println();
	}
}
//适配器设计模式
List<Integer> list = new ArrayList(Arrays.asList(ia);
Collections.shuffle(list, rand);
//此时list被打乱,ia不会被打乱
Collections.shuffle(Arrays.asList(ia),rand);
//此时ia作为List的底层数组会被打乱
  • Collection:List Set Queue
  • Map:Map
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值