基础知识巩固四(问题部分)
一、关于java多态
多态的存在有三个前提:
- 要有继承关系
- 子类要重写父类的方法
- 父类引用指向子类对,
二、观察Set中的add源码(扩容)
调试了一下,发现set底层接触到了hashmap,hashmap的扩容方法resize(),每次扩容,都是原来大小的两倍,里头具体的代码没去深究,知道有这么个事儿。
定义初始容量大小(table数组的大小,缺省值为16),定义负载因子(缺省值为0.75)的形式
三、for-each循环set
集合类可以用for-each形式输出整个集合,也可以用Iterator.
for-each注意点:
- 要使用for-each语法,必须是数组,或者该类必须实现Iterable接口才可以
- foreach循环的内部实现也是依靠Iterator进行实现的
for(T t : Iterable) { .... }
如果查看编译后的字节码,会发现foreach最终被编译器转为对iterator.next()的调用,这些jdk给隐藏起来了
注意:
- foreach循环只适用于实现了Iterable<T>接口的对象。由于所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable,所以为了解决上述问题,可以选择简单地让CustomCollection实现Collection接口或者继承AbstractCollection
四、比较器实现一个Comparator
在idea中代码如下:
1 public class Test<T> { 2 3 public static void main(String[] args){ 4 System.out.println("It's for String"); 5 CompareBoth<String> sg = new CompareBoth<String>(); 6 System.out.println(sg.compare("asd", "asd")); 7 System.out.println(sg.compare("a", "d")); 8 System.out.println("It's for Integer"); 9 CompareBoth<Integer> in = new CompareBoth<Integer>(); 10 System.out.println(in.compare(1,2)); 11 System.out.println(in.compare(1,1)); 12 System.out.println(in.compare(2,1)); 13 } 14 15 private static class CompareBoth<T> implements Comparator<T>{ 16 17 public int compare(T o1, T o2) { 18 if (o1 instanceof String){ 19 if(o1.equals(o2))return 0; 20 } 21 if (o1 instanceof Integer){ 22 if (((Integer) o1).intValue()==((Integer)o2).intValue())return 0;//int a = A.valueOf()可以将Integer的A转换成int23 if ((Integer)o1>(Integer) o2)return 1; 24 } 25 return -1; 26 } 27 } 28 }
五、线性表概念
首先补充一个概念,集合分为:1、规则集(Set) 2、线性表(List)3、队列(queue)
线性表:线性表主要由顺序表示或链式表示。
- ArrayList是通过数组实现的顺序存储线性表
- LinkedList是通过链表实现的链式存储线性表。
六、Entry
Entry是Map中用来保存一个键值对的,而Map实际上就是多个Entry的集合,Entry是Map实现类的内部类。
Entry是为了输出的方便,一般情况下,要输出Map中的key 和 value 是先得到key的集合,然后再迭代(循环)由每个key得到每个value,而Entry可以一次性获得这两个值
其中的主要方法有:
- entrySet():返回一个包含图中条目的规则集,也就是获得了Map所有的Key与value的集合。Set<Map.Entry<K,V>>
- keySet():返回包含图中键值的一个规则集,也就是获得key的集合。Set<K>
- values():返回包含图中值的集合。Collection<V>
代码部分:
1 public class Test { 2 public static void main(String[] args){ 3 Map<String,Integer> map = new HashMap<>(); 4 map.put("小明",1); 5 map.put("小丽",2); 6 map.put("小张",3); 7 Set<Map.Entry<String,Integer>> entry = map.entrySet(); 8 Iterator<Map.Entry<String,Integer>> it = entry.iterator(); 9 while(it.hasNext()){ 10 Map.Entry<String,Integer> e= it.next();
System.out.println("name:"+e.getKey()+";value:"+e.getValue()); 11 } 12 //获取键值来获取Value 13 Set<String> names = map.keySet(); 14 Iterator itName = names.iterator(); 15 while(itName.hasNext()){ 16 String v = (String) itName.next(); 17 System.out.println("name:"+v+";value:"+map.get(v)); 18 } 19 //直接获取values值的集合 20 Collection<Integer> values = map.values(); 21 Iterator itValue = values.iterator(); 22 while(itValue.hasNext()){ 23 System.out.println(itValue.next()); 24 } 25 } 26 }
注意点:
entrySet和KeySet方法返回的都是一个Set的集合
values()返回的是一个Collection的集合
Iterator<Map.Entry<String,Integer>> it = entry.iterator();必须指定迭代器的泛型,不然会出现如下的提示
Incompatible types.
Required:java.util.Map.Entry<java.lang.String,java.lang.Integer>
Found:java.lang.Object>
这个情况可以使用强制类型转换,不过最好还是在前面迭代器就定义好泛型。
参考链接:http://kingdelee.iteye.com/blog/1580463
七、去除正则表达式中的空格
\s表示的是空格,那么可以这样写
1 public class Test<T> { 2 public static void main(String[] args){ 3 String regex = "\\s+"; 4 String str = " asd asd asdas asd asd sad "; 5 str = str.trim();//去掉开头结尾空格 6 String str1 = str.replaceAll(regex," ");//将字符串中多个空格转为一个空格 7 String str2 = str.replaceAll(regex,"");//将字符串中空格删除 8 System.out.println(str1); 9 System.out.println(str2); 10 } 11 }
八、优先队列PriorityQueue
优先队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。PriorityQueue是从JDK1.5开始提供的新的数据结构接口。
如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列。
如果想实现按照自己的意愿进行优先级排列的队列的话,需要实现Comparator接口。
PriorityQueue有四种构造方法
- 无参数构造方法PriorityQueue():创建一个初始容量为11的默认优先队列
- PriorityQueue(initialCapacity:int):创建一个带指定容量的默认优先队列
- PriorityQueue(c:Collection<? extends E>):创建一个带指定集合的优先队列
- PriorityQueue(initialCapacity:int,comparator:Comparator<? super E>):创建一个带指定初始容量和比较器的优先队列
今天主要尝试了后两种,第三种的代码如下:
1 public class Test { 2 public static void main(String[] args){ 3 Queue<Fruit> queue = new PriorityQueue<>(new Fruit()); 4 queue.offer(new Fruit("小明",0)); 5 queue.offer(new Fruit("小美",3)); 6 queue.offer(new Fruit("小智",2)); 7 queue.offer(new Fruit("小丽",1)); 8 for (Fruit f:queue){ 9 System.out.println(f.getName()); 10 } 11 } 12 13 private static class Fruit implements Comparator<Fruit>{ 14 private String name; 15 private int priority; 16 public Fruit(){} 17 public Fruit(String name,int priority){ 18 this.name = name; 19 this.priority = priority; 20 } 21 22 23 public String getName() { 24 return name; 25 } 26 27 public int getPriority() { 28 return priority; 29 } 30 31 public int compare(Fruit o1, Fruit o2) { 32 int first = o1.getPriority(); 33 int last = o2.getPriority(); 34 if (first>last){ 35 return 1; 36 }else if (first==last){ 37 return 0; 38 }else { 39 return -1; 40 } 41 } 42 43 } 44 }
第四种代码是使用匿名内部类自定义一个比较器然后放到priorityQueue中:
1 Comparator<Fruit> comparator = new Comparator<Fruit>(){ 2 public int compare(Fruit o1, Fruit o2) { 3 int numbera = o1.getPopulation(); 4 int numberb = o2.getPopulation(); 5 if(numberb > numbera) 6 { 7 return 1; 8 } 9 else if(numberb<numbera) 10 { 11 return -1; 12 } 13 else 14 { 15 return 0; 16 } 17 }
Queue<Fruit> priorityQueue = new PriorityQueue<Fruit>(11,comparator);
参考链接:http://blog.csdn.net/hiphopmattshi/article/details/7334487
九、关于Vector
1. Vector & ArrayList
- Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
- 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
2. Hashtable & HashMap
- Hashtable和HashMap它们的性能方面的比较类似 Vector和ArrayList,比如Hashtable的方法是同步的,而HashMap的不是。
代码部分:
1 public class Test { 2 public static void main(String[] args){ 3 Vector vector = new Vector(); 4 long begin = System.currentTimeMillis(); 5 for (int i = 0;i<100000;i++) 6 vector.add(i); 7 System.out.println("Vector花费的时间"); 8 System.out.println(System.currentTimeMillis()-begin); 9 List list = new ArrayList(); 10 long lbegin = System.currentTimeMillis(); 11 for (int i = 0;i<100000;i++) 12 list.add(i); 13 System.out.println("ArrayList花费的时间"); 14 System.out.println(System.currentTimeMillis()-lbegin); 15 } 16 }