基礎筆記(後端)

記錄一些簡單基礎但是總有時候會突然記混或者忘記的碎片化知識。

一、關於 “==”和equals()。區別一直都知道。用“==”時,如果是八大基礎類型進行則是比較他們的“值”。如果是對象則是比較所指向的地址。equals()常用於 “值“的比較。但是經常還是會犯錯誤。用一個簡單的代碼驗證。

public static void main(String[] args) {
		FinalDemo f=new FinalDemo();
		int b=11;
		String a1="a"+"b"+1;
		String b1="ab1";
		
		String a2="a"+"b"+b;
		String b2="ab11";
		System.out.print("a1和b1比較結果:");
		System.out.println(a1==b1);
		System.out.print("a2和b2比較結果:");
		System.out.println(a2==b2);
	}


輸出結果。

原因:在變量a1中。由於jvm的“編譯時的優化”,默認認爲“a”、"b" 和1都是常量,因爲3個常量相加的結果是一致的。所以運行的時候就不在做計算。會把String a1="a"+"b"+1編譯成String a1="ab1"。這樣a1所指向的就和b1的指向的相同了。第一個比較結果爲true。同理可得a2和b2就不一樣了。因爲a2中存在着一個變量 int b。參考於《JAVA特種兵》一書。

二、String類的intern()方法

不做重複記錄。發現一篇研究講解很透徹的文章。

Java技術——你真的瞭解String類的intern()方法嗎

三、最簡單快速的桶排序

這個名字我居然以前沒怎麼聽過,也是醉了。。。但其實發現雖然沒聽過,但是平時用到的次數絕對不少,只是不知道叫什麼名。特此記錄。

例如對一組數排序 2,6,100,2,45,5,1。桶排序的前提是知道要排序的範圍(可能是這個限制導致,適用率太低,對名稱的熟悉度不夠)。這兒的這組數中,範圍是[0,100]。那麼定義一個大小爲101一維數組bucket[101],記錄每個數出現的次數。該數組的下標對應的就是我們要排序的數。

代碼

public static void main(String[] args) {
    	//需要排序的數
        int[] number = new int[]{2,6,100,2,45,5,1};   
        //用於記錄出現次數的桶
        int[] bucket=new int[101];
        
        //記錄每個數出現的次數,(官方說法是將要排序的數放入桶中)
        for(int i=0;i<number.length;i++){
        	bucket[number[i]]++;
        }
        
        //遍歷桶,輸出排序後的結果
        for(int i=0;i<bucket.length;i++){
        	for(int j=0;j<bucket[i];j++){
        		System.out.println(i);
        	}
        }
    } 
結果

特性:時間複雜度較小但是空間複雜度則比較大,所以桶排序雖簡單且快,但不適合數據跨度較大的使用場景。同時桶排序是不穩定的。由於大多數排序場景不確定數據跨度,因此桶排序很少被使用。

四、冒泡排序

基本上大家都知道的排序,但是由於效率太差很少被使用,原理就是循環的比較相鄰的數,把大的和小的分別向後和向前推。每一輪找出最大的一個。

public static void main(String[] args) {    
        int[] number = new int[]{2,6,100,2,45,5,1}; 
        int temp;
        for(int i=0;i<number.length-1;i++){
        	for(int j=0;j<number.length-i-1;j++){
        		if(number[j]>number[j+1]){
        			temp=number[j];
        			number[j]=number[j+1];
        			number[j+1]=temp;
        		}
        	}
        }
        for(int i=0;i<number.length;i++){
        	System.out.println(number[i]);
        }
    }
特性:限制比桶排序小,但是比較次數過多,導致效率較差。但是可以做相應的修改。

1、每次排序後比較下是否排完。

public static void main(String[] args) {
        boolean flag=true;
        int[] number = new int[]{2,6,100,2,45,5,1}; 
        int temp;
        for(int i=0;i<number.length-1;i++){
            if(!flag){
                for(int j=0;j<number.length-i-1;j++){
                    if(number[j]>number[j+1]){
                        temp=number[j];
                        number[j]=number[j+1];
                        number[j+1]=temp;
                    }
                }
            }
            for(int j=0;j<number.length-i-1;j++){
                if(number[j]>number[j+1])
                    flag=false;
                }
            }
            for(int i=0;i<number.length;i++){
                System.out.println(number[i]);
            }

        }
優缺點:對有些數據比如 1,2,3,4,5,6,7,8 可能能很快結束排序。但是如果是8,7,6,5,4,3,2,1反而更加耗時。不建議使用。
2、標記法

定義一個boolean變量flag。只要是每次出現順序替換的情況就將變量設置爲false。每輪結束後判斷flag就可以看出是否排序完成。

public static void main(String[] args) {
    	boolean flag=true;
        int[] number = new int[]{2,6,100,2,45,5,1}; 
        int temp;
        for(int i=0;i<number.length-1;i++){
        	for(int j=0;j<number.length-i-1;j++){
            	if(number[j]>number[j+1]){
            		temp=number[j];
            		number[j]=number[j+1];
            		number[j+1]=temp;
            		flag=false;
            	}
            }
        	if(flag){
        		break;
        	}
        	
        }
        for(int i=0;i<number.length;i++){
        	System.out.println(number[i]);
        }

    }

五、快速排序。

以前總以爲自己知道這個,最近想自己要寫一下的時候才知道自己一直在偏自己。

原理:每次在需要排序的數中選一個作爲標準數,分別從右到左和從左到右對需要排序的部分進行比較,找到第一個比標準數大或者小的數,然後與標準數替換,最後是比標準大數全部放右邊,小的全部放左邊,依次反覆得到最佳結果。

public static void  quickSort(int[] number,int begin,int end){
    	if(begin<end){
    		//標準數
       	 int key=number[begin];
       	 int i=begin;
       	 int j=end;
       	 while(i<j){
       		 //找出從右到左第一個比標準數要小的數
       		 while(i<j&&number[j]>key){
       			 j--;
       		 }
       		 //將從右到左第一個比標準數小的和標準數互換
       		 if(i<j){
       			 number[i]=number[j];
       			 //這一部分其實省略了一句代碼
       			 //number[j]=key;
       			 i++;
       		 }
       		 //找出從左到右第一個比標準數大的數
       		 while(i < j && number[i]<key){  
                    i++;  
                }  
       		 //將找到的數和標準數互換
                if(i < j){  
               	 number[j] = number[i];
               	 //同樣,這部分也省略了一部分代碼
               	 //number[i]=key;
                    j--;  
                }  
       		 	 
       	 }
       	 //一輪結束後,分爲兩部分,左邊的全是比標準數小的,右邊全是比它大的,因爲上面省略了代碼。所以下面需要把最後的一個空位置留給key
       	 number[i] = key;
       	 //對剩餘的兩部分繼續重複
       	 quickSort(number, begin, i-1);
       	 quickSort(number, i+1, end);
    	}
    	 
    	 
    }
        
    public static void main(String[] args) {    
    	int[] number = new int[]{2,6,100,2,45,5,1};
    	quickSort(number,0,6);
    	for(int i=0;i<number.length;i++){
    		System.out.println(number[i]);
    	}
    }

特點:需排序數多的情況下性能比其他的快,否則和其他排序法性能差不多,如果排序的數本身就是有序的情況下性能最差。大數據量的情況下,適合和插入排序法一起使用。先用快速排序法將數據分爲幾個區域較小但是大致有序區間,然後使用插入排序法。

六、插入排序

分爲直接插入和二分插入。插入法會將待排序數據默認分爲兩個部分:排好序部分和待排序部分。如果是直接插入法可以默認其中第一個數爲排好序的部分,然後拿其餘的待排序部分去和第一個數比,判斷插入到合適的位置。此時排好序的數據就有兩個了,接着繼續重複上面的步驟,直到待排序數據全部插入到排好序的部分。二分插入則是對直接插入的優化。每次取排好序數據中的對半位置的數進行比較。

直接插入

public static void Sort(int [] number){
    	int temp;
    	for(int i=1;i<=number.length-1;i++){
    		temp=number[i];
    		//與排好序的部分進行比較,第一次默認爲第一個數,後續會逐漸增多
    		for(int j=i-1;j>=0;j--){
    			if(number[j]>temp){
    				number[j+1]=number[j];
    				number[j]=temp;
    			}else{
    				break;
    			}
    		}
    	}
    	for(int i=0;i<number.length;i++){
    		System.out.println(number[i]);
    	}
    	
    }
二分插入
public static void Sort(int[] number ){
    	int temp,start,end,mid;
    	//同直接排序一樣,以第一個爲默認排好序的部分
    	for(int i=1;i<=number.length-1;i++){
    		temp=number[i];
    		//對排好序的部分進行二分,以此比較
    		 start=0;
    		 //排好序的部分最大位置範圍
    		 end=i-1;
    		 mid=0;
    		
    		while(start<=end){
    			mid=(start+end)/2;
    			//現有數據對摺比較,如果大於則取前面一部分,小於則取後面一部分繼續比較。
    			if(number[mid]>temp){
    				end=mid-1;
    			}else{
    				start=mid+1;
    			}
    		}
    		//排除位置不變的情況 i與start相等的時候表明位置不變
    		if(i!=start){
    			//位置有改變,開始插入的部分向後移動
    			for(int j=i;j>start;j--){
    				number[j]=number[j-1];
    			}
    			//空出來的位置填入進行比較的數【temp】
    			number[start]=temp;
    			
    		}
    		
    	}
    	
    	for(int i=0;i<number.length;i++){
    		System.out.println(number[i]);
    	}
    }
    
    public static void main(String[] args) {    
    	int[] number = new int[]{2,6,100,2,45,5,1};
    	Sort(number);
    	
    	
    }

還有幾種等有空在補充。分別是希爾排序、選擇排序、堆排序、歸併排序。


框架:

springmvc靜態資源無法訪問以及配置導致可以訪問靜態資源但是無法訪問controller。

經常發現頁面中的js無法訪問,這是因爲springMvc需要對靜態資源進行配置。一般用如下配置即可,默認根目錄從webapp開始。主要原因是springMvc原來沒辦法較好的處理各種靜態資源的訪問。需要在請求後帶各種後綴。如果不帶後綴則需要自己進行配置。

<mvc:resources location="/WEB-INF/view/pages" mapping="/pages/**"/>
    <mvc:resources location="/WEB-INF/view/images/" mapping="/images/**"/>  
    <mvc:resources location="/WEB-INF/view/javasrcipt/" mapping="/javasrcipt/**"/>
    <mvc:resources location="/WEB-INF/view/bootstrap/" mapping="/easyui/**"/>  
    <mvc:resources location="/WEB-INF/view/css/" mapping="/css/**"/>
    <mvc:resources location="/WEB-INF/view/jquery/" mapping="/jquery/**"/> 

對應的jsp頁面如下就能訪問到靜態資源。

<%String path = request.getContextPath();%>
<script src="<%=path%>/jquery/jquery.min.js"></script>
    <script src="<%=path%>/bootstrap/js/bootstrap.js"></script>

但是這樣弄了之後可能導致你的controller無法訪問了。

只需要在配置靜態資源的最上方加一句 <mvc:annotation-drivern/>就可以了

<mvc:annotation-driven />
<mvc:resources location="/WEB-INF/view/pages" mapping="/pages/**"/>
    <mvc:resources location="/WEB-INF/view/images/" mapping="/images/**"/>  
    <mvc:resources location="/WEB-INF/view/javasrcipt/" mapping="/javasrcipt/**"/>
    <mvc:resources location="/WEB-INF/view/bootstrap/" mapping="/easyui/**"/>  
    <mvc:resources location="/WEB-INF/view/css/" mapping="/css/**"/>
    <mvc:resources location="/WEB-INF/view/jquery/" mapping="/jquery/**"/> 

還有一種方法就是在web.xml進行配置,這樣就不需要在springMvc中配置了

    <servlet-mapping>    
             <servlet-name>default</servlet-name>    
             <url-pattern>*.png</url-pattern>  
             <url-pattern>*.js</url-pattern>  
             <url-pattern>*.jpg</url-pattern>  
             <url-pattern>*.css</url-pattern>  
    </servlet-mapping>  


註解:@Autowired和@Resource

對類成員變量、方法及構造函數進行標註,完成自動裝配的工作。 消除 set ,get方法。

例如,User類擁有name和age兩個屬性。


圖片等價於下面的xml配置

<bean id="controller" class="com.y.demo.controller"/>     
          <bean id="user" class="com.y.demo.User">     
            <property name="name" value="用戶1"/>
            <property name="age" value="18"/>
        </bean>     
       </bean>
使用@Autowired必須在xml裏面做一下聲明
<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/> 

@Resource的用處和@Autowired相似,主要差別是@Autowired是根據類型注入。用上面的例子說就是注入到bean裏面是通過User這個類來進行的,後續查找使用也是根據bean的類型進行查找。

如果使用@Resource(name="user1")來進行註解,  通過此註解完成從spring配置文件中查找名稱爲user1的bean來裝user,如果spring配置文件中不存在 user1名稱的bean則轉向按照bean的類型經行查找,也就查看有沒有叫做 user1的類。

此時圖中對應的xml爲下面的樣子
<bean id="controller" class="com.y.demo.controller"/>     
          <bean id="user1" class="com.y.demo.User">     
            <property name="name" value="用戶1"/>
            <property name="age" value="18"/>
        </bean>     
       </bean>

使用@Resource必須的聲明如下

<bean class="org.springframework.beans.factory.annotation. CommonAnnotationBeanPostProcessor"/>



@RequestParam和@PathVariable的區別 摘抄自此處  http://blog.csdn.net/u011410529/article/details/66974974

@RequestParam@PathVariable 註解是用於從request中接收請求的,兩個都可以接收參數,關鍵點不同的是@RequestParam 是從request裏面拿取值,而 @PathVariable 是從一個URI模板裏面來填充

@RequestParam

看下面一段代碼:

http://localhost:8080/springmvc/hello/101?param1=10&param2=20

根據上面的這個URL,你可以用這樣的方式來進行獲取

public String getDetails(
    @RequestParam(value="param1", required=true) String param1,
        @RequestParam(value="param2", required=false) String param2){
...
}

@RequestParam 支持下面四種參數

  • defaultValue 如果本次請求沒有攜帶這個參數,或者參數爲空,那麼就會啓用默認值
  • name 綁定本次參數的名稱,要跟URL上面的一樣
  • required 這個參數是不是必須的
  • value 跟name一樣的作用,是name屬性的一個別名

@PathVariable

這個註解能夠識別URL裏面的一個模板,我們看下面的一個URL

http://localhost:8080/springmvc/hello/101?param1=10&param2=20

上面的一個url你可以這樣寫:(請求路徑裏面的id,當成模板來運用)

@RequestMapping("/hello/{id}")
    public String getDetails(@PathVariable(value="id") String id,
    @RequestParam(value="param1", required=true) String param1,
    @RequestParam(value="param2", required=false) String param2){
.......
}

區別很明顯了


常用註解


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章