基础知识巩固四(问题部分)

一、关于java多态

多态的存在有三个前提:

  1. 要有继承关系
  2. 子类要重写父类的方法
  3. 父类引用指向子类对,

二、观察Set中的add源码(扩容)

调试了一下,发现set底层接触到了hashmap,hashmap的扩容方法resize(),每次扩容,都是原来大小的两倍,里头具体的代码没去深究,知道有这么个事儿。

定义初始容量大小(table数组的大小,缺省值为16),定义负载因子(缺省值为0.75)的形式

三、for-each循环set

集合类可以用for-each形式输出整个集合,也可以用Iterator.

for-each注意点:

  1. 要使用for-each语法,必须是数组,或者该类必须实现Iterable接口才可以
  2. 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可以一次性获得这两个值

其中的主要方法有:

  1. entrySet():返回一个包含图中条目的规则集,也就是获得了Map所有的Key与value的集合。Set<Map.Entry<K,V>>
  2. keySet():返回包含图中键值的一个规则集,也就是获得key的集合。Set<K>
  3. 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有四种构造方法

  1. 无参数构造方法PriorityQueue():创建一个初始容量为11的默认优先队列
  2. PriorityQueue(initialCapacity:int):创建一个带指定容量的默认优先队列
  3. PriorityQueue(c:Collection<? extends E>):创建一个带指定集合的优先队列
  4. 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

  1. Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
  2. 当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 }
原文地址:https://www.cnblogs.com/shigeng/p/8537881.html