Stack/Set/Map/Queue浅析
2017-07-21 15:36
183 查看
栈
“栈”通常是表示“后进先出”的容器。就好比在盘子里叠入披萨,最后放进去的总是在最上面。 ListkedList具有能直接实现栈的所有功能的方法,因此可以直接将LinkedList当作栈使用。 不过,有时候一个真正的“栈”更能把事情说明白:
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(); } }
这里使用泛型,引入了在栈的类定义中最简单的可行示例。T表示告诉编译器这是参数化的类型,实际类型会在使用时被替换。如果我们只需要栈的行为,那使用继承就不合适了,因为这样就会产生具有LinkedList的其他所有方法的类。
public static void main(String[] args) { //创建具有泛型T的Stack类。并声明了T为String类型 Stack<String> stack = new Stack<String>(); for(String s : "My dog has fleas".split(" ")){ stack.push(s); } while (!stack.empty()) { //pop()方法是移除栈顶元素,并且返回。 System.out.println(stack.pop() + " "); } }
Set
Set不保存重复元素。如果我们需要查询功能,那么用hashSet是很好的选择,因为它专门针对了查找进行优化。 Set和Collection有完全一样的接口。实际上Set就是Collection,只是行为不同。行为的不同是继承和多态的典型应用。Set是基于对象的值来确定归属的。
public static void main(String[] args) { Random rand = new Random(47); Set<Integer> intset = new HashSet<Integer>(); for(int i = 0; i < 10000; i++){ intset.add(rand.nextInt(30)); } System.out.println(intset); } //out [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
在hashSet中插入了0-29的10000个随机数,但是实际结果只有0-29,并且是无序的。这里的无序指的是存入和取出的顺序不一致。因为考虑到速度原因,HashSet用到了散列。其顺序与TreeSet和LinkedHashSet都不同,因为他们的实现具有不同的元素存储方式。TreeSet将元素存储在红-黑树数据结构中,而HashSet是散列函数。LinkedHashSet也使用了散列,但是看起来它使用了链表来维护插入顺序。如果我们需要排序,可以用TreeSet来替换HashSet,默认安装字典排序,并且区分大小写。如果想用字母排序,可以向TreeSet构造器传入String.CASE_INSENTIVE_ORDER
public static void main(String[] args) { String sort = "A B C J Y O M G M U O aa b c j y o m g m u o"; Set<String> words = new TreeSet<String>(); for(String s : sort.split(" ")){ words.add(s); } System.out.println("not set para:" + words); Set<String> words2 = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); for(String s : sort.split(" ")){ words2.add(s); } System.out.println("use set para:" + words2); } //out not set para:[A, B, C, G, J, M, O, U, Y, a, b, c, g, j, m, o, u, y] use set para:[A, aa, B, C, G, J, M, O, U, Y]
很明显String.CASE_INSENSITIVE_ORDER虽然是按照字符排序了,但是其实际含义是不区分大小写。也就是B和b只能在Set中存在一个了。
Map
将对象映射到其他对象的能力是一种解决编程问题的杀手锏。
public static void main(String[] args) { Random rand = new Random(47); Map<Integer, Integer> m = new HashMap<>(); for(int i = 0; i < 10000; i++){ int r = rand.nextInt(20); Integer freq = m.get(r); m.put(r, freq == null ? 1:freq+1); } System.out.println(m); } //out {0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, 14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
自动包装机制,将随机生成的int转换成了Integer类型,用生成的int类型去Map中找,是否有该key,如果没有会返回null,如果有则会返回对应的value值。为null的情况会赋值给freq为1,不为null就进行累加。在累加中,自动拆包又进行的操作,否则Integer不能进行累加的。
Map与数组和其他的Collection一样。可以很简单的扩展到多维结果,比如Map<Stirng,Map<Integer,String>>或者更复杂的数据结构。
//这句话表示,该变量petPeople的数据类型是Map,而Map中key是String,value是List。这个List的类型是未知但且继承String public static Map<String,List<? extends String>> petPeople = new HashMap<>(); static{ petPeople.put("Dawn", Arrays.asList("Molly","Spot")); petPeople.put("Kata", Arrays.asList("Shackleton","Elsie May","Margrett")); petPeople.put("Marilyn", Arrays.asList("Louie aka Louis Snorkelstein Dupree", "Stanford aka Srinky el Negro", "Pinkola")); petPeople.put("Luke", Arrays.asList("Fuzzy","Fizzy")); petPeople.put("Isaac", Arrays.asList("Freckly")); } public static void main(String[] args) { //keySet返回了所有key组成的Set System.out.println("People: " + petPeople.keySet()); //values返回了所有对应的value,根据Set的默认排序 System.out.println("Pets: " + petPeople.values()); for (String string : petPeople.keySet()) { System.out.println(string + " has:"); for (String s : petPeople.get(string)) { System.out.println(" " + s); } } }
Queue
队列是保持先进先出,和LinkedList相反。就像排队打饭一样,先排队的人,就能先打到饭,排除插队的情况。 队列在并发编程中特别重要,因为它们可以安全地将对象从一个任务传给另一个任务。 LinkedList提供了方法以支持队列的行为,并且它是想了Queue接口,因此LinkedList可以用做Queue的一种实现。通过将LinkedList向上转型为Queue。
public static void printQ(Queue queue){ while(queue.peek() != null){ System.out.print(queue.remove() + " "); } } public static void main(String[] args) { Queue<Integer> queue = new LinkedList<>(); Random rand = new Random(47); for (int i = 0; i < 10; i++) { queue.offer(rand.nextInt(i+10)); } printQ(queue); }
offer()将一个元素插入到队列尾端。在将LinkedList转化为Queue后,LinkedList的方法会不能使用。当然我们可以将Queue又转成LinkedList。
PriorityQueue
PriorityQueue在Java SE5中被添加,是为了提供这种行为的一种自动实现。 当你在PriorityQueue上调用offer()方法来插入一个对象时,这个对象会在队列中被排序。默认的排序将使用对象在队列中的自然顺序,但是你可以通过提供自己的Comparator来修改这个顺序。PriorityQueue可以确保当你在调用Peel(),poll()和remove()时,获取的是最高优先级的元素。
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<>(); Random rand = new Random(47); for (int i = 0; i < 10; i++) { //队列存值 priorityQueue.offer(rand.nextInt(i + 10)); } //输出第一次删除被返回的值 PriorityQueueDemo.printQ(priorityQueue); //构建ints的List容器。此种构建方式,不允许被add List<Integer> ints = Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25); //将此List给优先级队列 priorityQueue = new PriorityQueue<>(ints); PriorityQueueDemo.printQ(priorityQueue); priorityQueue = new PriorityQueue<>(ints.size(),Collections.reverseOrder()); priorityQueue.addAll(ints); PriorityQueueDemo.printQ(priorityQueue); }
由此可以看出,队列运行重复,数字小的优先级高(比字母高)。大写字母比小写字母优先级高。 Collections.reverseOrder()同样是在JAVA SE5中增加的反序Comparator。
下节会讲Collection和Iterator和Foreach和适配器方法惯用法
相关文章推荐
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)zhuanzai
- Map、Set、List、Queue、Stack的特点与用法
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)(转)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- Map、Set、List、Queue、Stack的特点与用法1
- STL详解(vector,list,deque,stack,queue,priority_queue;map,set)
- Map、Set、List、Queue、Stack的特点与用法2
- java中List、Map、Set、Collection、Stack、Queue等的使用
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- Map、Set、List、Queue、Stack的特点与用法。
- [],List,Set,Map,Table,Queue,Deque,Stack性能分析
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- STL容器用法速查表:list,vector,stack,queue,deque,priority_queue,set,map