Java编程思想读书笔记-5

第11章 持有对象

11.2 基本概念

Collection

List必须按照插入的顺序保存元素,而Set不能有重复元素,Queue按照排队规则来确定对象产生的顺序(通常与插入顺序保持一致)

Map

一组成对的"键值对"对象,允许使用键值来查找值。

11.3 添加一组元素

import java.util.Arrays;
import java.util.List;

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());
		
// Light 和 Heavy都是Powder,snow2的asList中只有Powder类型的,所以只会创建List<Powder>而不是List<Snow>
//		List<Snow> snow2 = Arrays.asList(
//				new Light(), new Heavy());
// 显示声明了类型
		List<Snow> snow3 = Arrays.<Snow>asList(
				new Light(), new Heavy());
	}
}

11.4 容器的打印

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

public class PrintContainers{
	static Collection<String> fill(Collection<String> collection){
		collection.add("rat");
		collection.add("cat");
		collection.add("dog");
		collection.add("dog");
		return collection;
	}
	
	static Map<String, String> 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>()));
		System.out.println(fill(new TreeMap<String,String>()));
		System.out.println(fill(new LinkedHashMap<String,String>()));
	}
}

结果:

[rat, cat, dog, dog]
[rat, cat, dog, dog]
[cat, dog, rat]
[cat, dog, rat]
[rat, cat, dog]
{cat=Rags, dog=Spot, rat=Fuzzy}
{cat=Rags, dog=Spot, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=Spot}
ArrayList和LinkedList都是List类型,按照插入的顺序保存元素。不同之处为两者在执行某些类型的操作时的性能,LinkedList包含的操作较多。

HashSet,TreeSet和LinkedHashSet都是Set类型,具有非重复性,但存储元素的方式不尽相同。HashSet具有最快获取元素的方式,TreeSet按照升序保存对象,LinkedHashSet按照添加的顺序保存对象。

HashMap,TreeMap和LinkedHashMap都是Map类型,通过键值可以来查找对象。HashMap具有最快获取元素的方式,TreeMap按照升序保存对象,LinkedHashMap按照添加的顺序保存对象。

11.5 List

ArrayList:适合随机访问,在但List中间插入和移除元素较慢

LinkedList:List中间插入和删除代价较低,提供了优化的顺序访问,但随机访问性能较差。

为什么不能用 new List()?

编程是要面向对象编程,针对抽象(接口),而非具体
List 是接口,ArrayList是实现
实现List接口的有ArrayList、LinkedList、Vector等,所以用哪个就直接new 一个接口实现
这是一种很好的设计模式.一个接口有多种实现,这种写法是java面向对象的一种思想,依赖倒置原则,即依赖于抽象不依赖于实现(具体)。
给调用者提供的应该是接口或者抽象类,而实现者可以实现或者继承接口或者抽象类来满足调用者,这样调用者不必知道实现者怎样操作,实现者也可以根据具体情,况去实现,这样去除了耦合。这就是java设计模式的基础思想之一。

11.6 迭代器

Iterator:hasNext(),next(),remove()(用于移除由next产生的最后一个元素),单向访问

ListIterator:只能用于List类的访问,并且可以双向移动 hasNext(),next(),remove(),set()

11.7 LinkedList

实现了基本的List接口。getFirst(),element(),peek()都为获取第一个元素,List为空则getFirst()和element()抛出NoSuchElementException,而peek()则返回null。

removeFirst(),remove(),poll()都为删除元素,List为空removeFirst()和remove()抛出NoSuchElementException,而poll()则返回null。

addFirst(),add(),addLast()都为添加元素,removeLast()移除并返回列表的最后一个元素。

11.8 Stack

后进先出LIFO

用LinkedList来实现Stack

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();}
}

11.10 Map

Mao与数组和其他的Collection一样,可以很容易扩展到多维。如Map<Person, List<Pet>>,表示有多个宠物的人的

11.11 Queue

先进先出FIFO 

优先级队列

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Set;

public class PriorityQueueDemo{ 
	
	public static void printQ(Queue queue){
		while(queue.peek() != null){
			System.out.print(queue.remove() + " ");
		}
		System.out.println();
	}
	
	public static void main(String[] args){
		PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
		Random random = new Random(47);
		for(int i = 0; i < 10; ++i){
			priorityQueue.offer(random.nextInt(i+10));
		}
		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);
		printQ(priorityQueue);
		priorityQueue = new PriorityQueue<Integer>(ints.size(), Collections.reverseOrder());
		priorityQueue.addAll(ints);
		printQ(priorityQueue);
		
		String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION";
		List<String> strings = Arrays.asList(fact.split(""));
		PriorityQueue<String> stringPQ = new PriorityQueue<String>(strings);
		printQ(stringPQ);
		stringPQ = new PriorityQueue<String>(strings.size(), Collections.reverseOrder());
		stringPQ.addAll(strings);
		printQ(stringPQ);
		
		Set<Character> charset = new HashSet<Character>();
		for(char c: fact.toCharArray()){
			charset.add(c);
		}
		PriorityQueue<Character> cQueue = new PriorityQueue<Character>(charset);
		printQ(cQueue);
	}
}
结果:

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 

11.13 Foreach与迭代器

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;

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){
			System.out.print(" " + s + " ");
		}
	}	
}
foreach可以与所有的Collection对象一起工作。原因是Java SE5中引入了Iterator接口(包含了产生Iterator的iterator()方法),并且Iterator接口被foreach用来在序列中移动。所以如果你创建了任何实现Iterable变量,都可以将它用于foreach中:

import java.util.Iterator;

public class IterableClass implements Iterable<String>{ 
	
	protected String[] words = "And that is how we know the Earch to be banana-shaped.".split(" ");
	
	public static void main(String[] args){
		for(String s: new IterableClass()){
			System.out.print(s + " ");
		}
	}

	@Override
	public Iterator<String> iterator() {
		// TODO Auto-generated method stub
		return new Iterator<String>(){
			private int index = 0;

			@Override
			public boolean hasNext() {
				// TODO Auto-generated method stub
				return index < words.length;
			}

			@Override
			public String next() {
				// TODO Auto-generated method stub
				return words[index++];
			}

			@Override
			public void remove() {
				// TODO Auto-generated method stub
				throw new UnsupportedOperationException();
			}
		};
	}	
}
foreach语句可以用于数组或其他任何Iterable,但是这并不意味者数组肯定是一个Iterable,而任何自动包装也不会自动发生

import java.util.Arrays;

public class ArrayIsNotIterable {  
	static <T> void test(Iterable<T> ib){
		for(T t : ib){
			System.out.print(t + " ");
		}
		System.out.println();
	}
	
	public static void main(String[] args){
		test(Arrays.asList(1,2,3));
		String[]strings = {"A","B","C"};
		//array可以用,但是它不是iterable
		//test(strings);
		test(Arrays.asList(strings));
	}
}

11.3.1 适配器方法惯用法

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

public class MultiIterableClass extends IterableClass {  
	
	public Iterable<String> resversed(){
		return new Iterable<String>(){
			@Override
			public Iterator<String> iterator() {
				// TODO Auto-generated method stub
				return new Iterator<String>(){

					int current = words.length-1;
					@Override
					public boolean hasNext() {
						// TODO Auto-generated method stub
						return current > -1;
					}

					@Override
					public String next() {
						// TODO Auto-generated method stub
						return words[current--];
					}

					@Override
					public void remove() {
						// TODO Auto-generated method stub
						throw new UnsupportedOperationException();
					}	
				};
			}
		};
	}
	
	public Iterable<String> randomized(){
		return new Iterable<String>(){

			@Override
			public Iterator<String> iterator() {
				// TODO Auto-generated method stub
				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.resversed()){
			System.out.print(s + " ");
		}
		System.out.println();
		for(String s:mic.randomized()){
			System.out.print(s + " ");
		}
		System.out.println();
		for(String s:mic){
			System.out.print(s + " ");
		}
	}
}
输出:

banana-shaped. be to Earch the know we how is that And 
is banana-shaped. Earch that how the be And we know to 
And that is how we know the Earch to be banana-shaped. 
Collection.shuffle()没有影响到原来的数组,只是打乱了shuffled中的引用,这样是因为randomized()方法用一个ArrayList将Arrays.asList()方法的结果包装了起来。如果Arrays.asList()方法产生的List被直接打乱,那么就会修改底层的数组。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class ModifyingArrayAsList {  
	
	public static void main(String[] args){
		Random random = new Random(47);
		Integer[] ia = {1,2,3,4,5,6,7,8,9,10};
		List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
		System.out.println("Before shuffling: " + list1);
		Collections.shuffle(list1, random);
		System.out.println("After shuffling: " + list1);
		
		System.out.println("array: " + Arrays.toString(ia));
		
		List<Integer> list2 = Arrays.asList(ia);
		System.out.println("Before shuffling: " + list2);
		Collections.shuffle(list2, random);
		System.out.println("After shuffling: " + list2);
		System.out.println("array: " + Arrays.toString(ia));
	}
}
第一种情况,Arrays.asList()的输出被传递给了ArrayList的构造器,这将创建一个引用ia的元素的ArrayList,因此打乱顺序不会影响该数组。如果直接使用Arrays.asList(ia)的结果,就会打乱ia的顺序。如果你执行的操作会修改这个list,并且你不想修改原来的数组,那么你就应该在另一个容器中创建一个副本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值