Thking in java(第四版)-查缺补漏(第11章)

背景

继续查缺补漏

1.注解

注解以“@”符号开头,可以接受参数。

 @SuppressWarnings注解及其参数表示只有有关“不受检查的异常”的警告信息应该被抑制。

2.散列码

Object的toString()方法,打印类名,后面跟随该对象的散列码的无符号十六进制表示,通过

hashCode()方法产生散列码。

 

3.Java容器类类库

(1)Collction: 一个独立元素序列,这些元素服从一条或多条规则。List必须按照插入的顺序保存元素;

Set不能有重复元素;Queuean按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。

(2)Map:一组成对的“键值对”对象,允许你使用键来查找值。

 4.可复用代码

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

List<Apple> apples=new LinkedList<Apple>();

如果想修改实现,只需要在创建的时候修改,如上所示。List是接口

5.Arrays.asList()

Arrays.asList()的输出,将其当作List,在这种情况下,其底层表示的是数组,因此不能调整尺寸。如果

修改了Arrays.asList()的输出,那么底层的数组也会被修改。

package c11;
import java.util.*;
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=Arrays.asList(
			new Crusty(),new Slush(),new Powder());
		//Won't compile:
//		List<Snow> snow2=Array.asList(new List(),new Heavy());
//		Compiler says:
//		found: java.util.List<Powder>
//		required :java.util.List<Snow>
//		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()); 
		
	}
}

创建snow4的时候,要插入<Snow>,告诉编译器对于有Arrays.asList()产生的List类型。这称为

显式类型参数说明。

6.TreeMap和TreeSet

TreeSet:按照比较结果的升序保存对象

TreeMap:按照比较结果的升序保存键。

7.ListIterator

只能用于各种List类的访问,可以双向移动

8.LinkedList

可以用作栈、队列双端队列

下面实现了一个栈,例如:

package c11;
import java.util.LinkedList;
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();}
	
}

9.Set

TreeSet将元素存储在红-黑树数据结构中,而HashSet使用的是散列函数。LinkedHashList因为查询

速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。

package c11;
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);
	}
}

TreeSet默认按字典序进行排序,如果想要按字母顺序排序,可以向TreeSet的构造器传入String.CASE_INSENTIVE_ORDER

比较器,例如:

Set<String> words=new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

10.Map

假设你正在跟踪有多个宠物的人,你所需要的是一个Map<Person,List<Pet>> 。

11.Queue

LinkedList提供了方法支持队列行为,并实现了Queue接口。

PriorityQueue:优先级队列声明下一个弹出元素是最需要的元素。默认的排序将使用对象在队列中的

自然顺序(最小的值拥有最高的优先级),我们可以提供自己的Comparator来修改这个顺序。例如:

priorityQueue=new PriorityQueue<Integer>
              (ints.size(),Collections.reverseOrder());

12.Collection和Iterator

AbstractCollection提供了Collection的默认实现。生成Iterator是将队列与消费队列的方法连接在一起

耦合度最小的方式,并且与实现Collection相比,它在序列类上所施加的约束也少得多。

13.Foreach与迭代器

foreach语法也可以用于Collection对象。 因为Colleciton接口继承了Iterable接口,Iterable接口包含能

够产生Iterator的iterator()方法,Iterator接口被foreach用来在序列中移动。

如果创建了实现Iterable的类,那么可以将它用于foreach语句中。例如:

package c11;
import java.util.*;
public class IterableClass implements Iterable<String> {
	protected String[] words=("And that is how"+"we know the Earth to be banana-shaped").split(" ");
	public Iterator<String> iterator(){
		return new Iterator<String>(){
			private int index=0;
			public boolean hasNext(){
				return index<words.length;
			}
			public String next(){	return words[index++];}
			public void remove(){	throw new UnsupportedOperationException();}
		};
	}
	public static void main(String[] args){
		for(String s:new IterableClass())
			System.out.print(s+" ");
	}
}

不存在任何从数组到Iterable的自动转换,必须自己动手执行这种转换。

采用适配器方法的惯用法,添加多种迭代方式,例如:

package c11;
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 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(){	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+" ");
	}
}

总结

(1)容器不能持有基本类型,但是自动包装机制会仔细地执行基本类型到容器中所持有的包装器类型之间的双向

转换。

(2)数组和List都是排好序的容器。

(3)如果要进行大量的随机访问就使用ArrayList;如果要经常从表中间插入或删除元素,应该使用LinkedList。

(4)各种Queue以及栈的行为,由LinkedList提供支持。

(5)HashMap设计用来快速访问;TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap

保持元素插入的顺序,通过散列提供了快速访问的能力。

(6)HashSet提供最快的查询速度,而TreeSet保持元素处于排序状态。LinkedHashSet以插入顺序保存元素。

(7)程序中应该避免使用Vector、Hashtable和Stack。

猜你喜欢

转载自blog.csdn.net/a614528195/article/details/81558072
今日推荐