赞
踩
对于变得强大,首先你能尽量做的,就是接受弱小的事实。
大部分情况下,我们在从输入流中读出数据的时候,不会对数据进行分析,不会想究竟用什么数据结构存储它比较好。一拍脑袋都怼进了数组里面,然后根据题意去一遍遍制定循环数组的规则,一遍一遍,直到完成任务。
这篇文章我们来谈谈几个简单的数据结构好吗。比如有些数据存储方式如果用队列(先进先出FIFO)的话,后面处理数据会更加方便。有一些存进栈(先进后出FILO)里面,后面对数据的处理会更方便。还比如有些数据是键值对的形式,我们当然可以用数组去存,但处理起来就麻烦多了。以及某些数据的重复项对解决问题没有作用,我们怎样去重的问题,一个个去判断吗?可以,耗时耗力,太麻烦,接下来我们就来简单说说怎样实现这几个简单的数据结构吧。(一切从简,记忆的东西越少越好。)
首先如果数据需要按“先进先出”的方式提取,也就是我们数据结构中学的“队列”。想一想中午吃饭时候的队伍,人家先排的在队首,也会先打完饭,先出队列。我们可以用stack类来实现。
对“先进后出”的提取方式,就是我们学的“栈”。尝试去想一口井,然后你开始“落井下石”,当把井填满的时候,你又开始从井里往外拿(有点像撑得),你先拿到的是最后放进去的那个大石头,最后拿完了,才能拿到你最开始丢下去的基石。我们可以用queue类来实现。
上面说了,减少记忆量,我们都不用,我们用一个结构实现上面两个功能——LinkedList。
LinkedList是个双向链表。
来看下怎样定义一个LinkedList对象:
LinkedList <Integer> l = new LinkedList <Integer>()
<>内的内容为list中元素的类型,还可以是自定义的类型,很强大。
对象的add方法往list中加入数据。这个方法可以模拟数据进栈或者进队的过程,那么怎样模拟队列或栈的取出过程呢。
用list对象的removeLast方法,这个方法删除list的最后一个数据并将其返回。
对于队列数据取出的模拟,估计也想到了,对应的removeFirst方法,删除list第一个数据并将其返回,也就是先进先出。
- public static void stack(){
- LinkedList <Integer> l = new LinkedList <Integer>();
-
- l.add(1);
- l.add(2);
- l.add(3);
-
- System.out.println(l.removeLast());
- System.out.println(l);
-
- }
-
- public static void queue(){
- LinkedList <Integer> l = new LinkedList <Integer>();
-
- l.add(1);
- l.add(2);
- l.add(3);
-
- System.out.println(l.removeFirst());
- System.out.println(l);
-
- }
模拟下栈和队列:
- public static void main(String[] args) {
- stack();
- queue();
- }
结果:
接下来我们来说下对于键值对数据怎样存储,提取的时候比较方便,数组当然可以。但是我们可以尝试着用map,用完之后,再存储键值对的时候你就不会想起数组了。
map有两个子类,hashMap和treeMap。为了减少记忆量,简单了解下,treeMap会对key排序,而hashMap的速度较快。所以如果你需要排序,用tree。只是存进去拿出来,用hash就可以。
How to define a object(和上面的如出一辙):
Map <String, Integer> map = new HashMap<String, Integer>();
How to put data in map?
额,题目就是答案,用put方法就行。
How to get data from map?
同上,用get就行。
- public static void hashMap(){
- Map <String, Integer> map = new HashMap<String, Integer>();
-
- map.put("English", 80);
- map.put("Math", 90);
- map.put("Compute", 100);
-
- System.out.println(map.keySet()); //.getClass() 同type
- System.out.println(map.get("Compute"));
- System.out.println(map.get("sad")); //return null
- System.out.println(map);
- }
用put方法把键值对放进map,通过get(key)取出,那么如果key不存在呢。它会返回null,别担心,不会抛出异常导致程序崩溃。
另外有个小技巧,map对象的keySet方法,可以返回map里的所有key值,类比也会想到,它还有个valueSet方法,不需解释了。
来看下结果:
这里写个怎样循环遍历一个个取出key值或者value值的小技巧(所有序列结构的遍历都可以使用这种方法,比起传统的for循环标准语句,高级了一些。会让别人对你发出“XX”的感叹。):
- for(String s: map.keySet()){
- System.out.println(map.get(s));
- }
-
- for(Integer i : map.values()){
- System.out.println(i);
- }
回去我们看下treeMap,还吃栗子吗?吃吧,拿都拿来了:
- public static void treeMap(){
- Map <String, Integer> map = new TreeMap<String, Integer>();
- map.put("English", 80);
- map.put("Math", 90);
- map.put("Compute", 100);
-
- System.out.println(map);
- }
基本上没有改变什么,就连put的顺序都是一样的。猜猜看最后的结果会是怎样,那几个科目是否还深爱着对方。
有看出什么不同吗?hashMap的结果:
You are right,它对key按字母顺序排序了,这就是区别了。
最后我们讲下数据去重,很多数据里面有重复值,而有些操作我们不需要计数,只想得到那些不同的值。一般情况下我们可能会一个个判断,看看这个值是否在我的数组里面,如果没有就放进去,有就丢掉。也行,但其实我们无论是学习数学还是计算机,我们都知道“集合”这个东西的一个重要特性就是不能含有相同元素。所以我们根本不用考虑,把所有的数据不加判断的一股脑放进set里面让它自己去重就完事了。这样你就可以在别人还一个个判断的时候,说句:“我好了,你们呢?”
去重后,我们一个强转list,就又回到了我们熟悉的领域,自己的地盘,直接可以使用了呀。
咳咳,你知道我下面要说啥......
- public static void hashSet(){
- Set <Integer> s = new HashSet<Integer>();
- s.add(3);
- s.add(2);
- s.add(1);
- s.add(3);
- s.add(4);
- System.out.println(s);
- System.out.println(s.getClass());
- LinkedList <Integer> l = new LinkedList<Integer>(s);
- System.out.println(l);
- System.out.println(l.getClass());
- }
结果:
我们已经完成去重了,我们做了啥?把数据放进set,然后转成list。我好了,你们呢。
同样的set有hashSet还有treeSet,我查到的是treeSet会对元素排序,不过我这里看来hashSet也对元素排了序。我们并没有按1、2、3、4的顺序add,但还是很工整。hash可能看tree不顺眼了吧,它可能想告诉tree:“我不但能做你的工作,还比你快!”
让我们祝福hash。
That's all. 这个系列不会再写了,我会找时间把前面的文章好好改改。有撰写不妥之处,望不惜吝教指出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。