11)Map
作者说将对象映射到其他对象的能力是解决编程问题的杀手锏。
确实,例如查看随机数的分布,如果真是随机数的话,那么10000次产生20以内的随机数,每个数字出现的次数应该是相近的。
public class TestMap { public static void main(String[] args) { Map<Integer,Integer> map = new HashMap<Integer,Integer>(); Random r = new Random(47); //map里面为空 System.out.println(map.get(1)); for (int i = 0; i < 10000; i++) { int j = r.nextInt(10); Integer temp = map.get(j); map.put( j ,temp == null ? 1 : temp+1); } System.out.println(map); } } //result:null //{0=994, 1=1033, 2=1010, 3=1014, 4=958, 5=1000, 6=1052, 7=980, 8=946, 9=1013}
数字确实是随机分布的,Map也很好用。
Map也用到多维。
Map<Person,List<TV>>;
12)Queue
先进先出,买基金的时候,由于后期追加购买,但是前期的基金已经满1个月,这样不用赎回费,然后问了客服之后发现,先买进的先赎回,然后自己大拍大腿,这不就是所谓的队列设计吗?
LinkedList实现了Queue接口。
对了,经常用到Random,竟然忘了说为什么作者传参用了47,其实Random传参是传入一个计算的种子,默认是系统时间,47在他看来一直是“魔幻数字”。
public class TestQueue { public static void main(String[] args) { Queue<Integer> q = new LinkedList<Integer>(); Random r = new Random(47); for (int i = 0; i < 10; i++) { //将一个元素插入队尾 q.offer(r.nextInt(12)); } //返回队头 System.out.println(q.peek()); System.out.println(q); } }
一、PriorityQueue
直接看例子:
public class TestPriorityQueue { public static void main(String[] args) { String s = "What 's your favorite number ,1 or 2?"; List<String> l = Arrays.asList(s.split("")); PriorityQueue<String> pq = new PriorityQueue<String>(l); while(pq.peek()!=null){ System.out.print(pq.remove()+" "); } } } result: [, , , , , b, , 1, , i, e, n, h, ', , a, o, 2, ?, y, t, t, o, u, u, m, r, e, r, f, ,, s, a, v, r, o, W, r] ' , 1 2 ? W a a b e e f h i m n o o o r r r r s t t u u v y
先级最高最先弹出,在优先队列里面 最小的值拥有最高的优先级,如果为String,从上面看,空格优先级最高。
直接输出并不会排序,这和我之前预想的不一样。
要顺序输出,需要用peek方法,返回队头,空返回null,然后remove的时候优先级高的会现出来。
public static void main(String[] args) { String s = "werwerwer"; List<String> l = Arrays.asList(s.split("")); PriorityQueue<String> pq = new PriorityQueue<String>(l); while (pq.peek() != null) { System.out.print(pq.remove() + " "); } pq = new PriorityQueue<String>(l); System.out.println(pq.peek()); pq.remove(); System.out.println(pq.peek()); pq.remove(); System.out.println(pq.peek()); } result: e e e r r r w w w e e
结果让我奇怪的是String里面有空格。这个看了字符串再回来解决。
13)Foreach与迭代器
foreach遍历:
public class Box { public static void main(String[] args) { Collection<String> c = new LinkedList<String>(); String s = "you are so great"; Collections.addAll(c,s.split(" ")); for(String string : c){ System.out.println(string); } } }
原来foreach是Java SE5引入的特性,因为同时也引入了Iterable接口,接口产生Iterator的Iterator方法,Iterable被Foreach用来在序列中移动。所以实现Iterable的接口的类都可以用于Foreach语句。
All Known Subinterfaces: BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>, Collection<E>, Deque<E>, DirectoryStream<T>, List<E>, NavigableSet<E>, Queue<E>, Set<E>, SortedSet<E>
其实Iterable的子接口有这么多,接下来实现Collection接口的自然也就实现了Iterable接口,所以也适用。
总结:
先看容器分类图:
点线为接口,实线为具体类,空心箭头指实现接口,实心箭头指某个类可以生成箭头所指向的类的对象。
1、数组可以存放对象,存放基本类型的数据,可以多维,就是容量不能改变。
2、Collection保存单一的元素,Map保存键值对。
3、List和数组类似,但是List可以自动扩充容量。大量随机访问使用ArrayList,经常进行插入删除操作,用LinkedList。
public class Box { public static void main(String[] args) { long start = System.currentTimeMillis(); Random r = new Random(47); LinkedList<Integer> l = new LinkedList<Integer>(); for(int i = 0; i< 1000000; i++){ l.add(r.nextInt(1000)); } long end = System.currentTimeMillis(); System.out.println(end - start); ArrayList<Integer> a = new ArrayList<Integer>(); for(int i = 0; i< 1000000; i++){ a.add(r.nextInt(1000)); } long end2 = System.currentTimeMillis(); System.out.println(end2 -end); } }
4、Map,HashMap用来快速访问,TreeMap保持键的排序,速度没HashMap快,LinkedHashMap保持元素排序,也通过散列也能快速访问,于两者中间。
5、Set元素不重复,TreeSet,HashSet,LinkedHashSet与Map的类似。
最后你会发现,这些容器可以存放对象,还可以无限大小,还可以帮你计数,这么神奇的类是怎么设计出来的,这就是学好数据结构的重要性了。